Author: WhoAmI
email: kccddb@gmail.com
Date: 20230517
Copyright: CC BY-NC-SA
思考 如何 改成 n 個 連線, 選一最快回應的?
POST 在 message-body 中傳送
GET 在 HTTP Request 中
/*
Simple send http header
non-blocking connect
Author: WhoAmI
DATE: 20230517
You may need getaddrinfo (Linux man 3), please STUDY DNS and the following four files
/etc/host.conf
resolver configuration file
/etc/hosts
host database file
/etc/nsswitch.conf
name service switch configuration
/etc/gai.conf (configuration file)
*/
#include <stdio.h>
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h> /* superset of previous */
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <arpa/inet.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <netinet/in.h>
//errno
#include <errno.h>
#define debugerr(x) x
#define TRY 20
#define debugx(x) x
/*
HTTP client
GET /index.html?ip=1234567&name=jone HTTP/1.1
Host: 127.0.0.1:9999
*/
int getaddr(char *url, char *ipstr4, char *ipstr6)
{
struct addrinfo hints, *res, *p;
int status;
char ipstr[INET6_ADDRSTRLEN];
int count=0;
memset(&hints, 0, sizeof hints);
// = AF_UNSPEC; // AF_INET or AF_INET6 to force version
hints.ai_family=AF_INET ; //IPv4
hints.ai_socktype = SOCK_STREAM;
if ((status = getaddrinfo(url, NULL, &hints, &res)) != 0) {
fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(status));
return 0;
}
debugx(printf("IP addresses for %s:\n\n", url));
for(p = res;p != NULL; p = p->ai_next) {
void *addr;
char *ipver;
// get the pointer to the address itself,
// different fields in IPv4 and IPv6:
if (p->ai_family == AF_INET) { // IPv4
struct sockaddr_in *ipv4 = (struct sockaddr_in *)p->ai_addr;
addr = &(ipv4->sin_addr);
ipver = "IPv4";
inet_ntop(p->ai_family, addr, ipstr4, sizeof ipstr);
count++;
} else { // IPv6
struct sockaddr_in6 *ipv6 = (struct sockaddr_in6 *)p->ai_addr;
addr = &(ipv6->sin6_addr);
ipver = "IPv6";
if(ipstr6)inet_ntop(p->ai_family, addr, ipstr6, sizeof ipstr);
debugx(printf(" %s: %s\n", ipver, ipstr));
}
//inet_ntop(p->ai_family, addr, ipstr, sizeof ipstr);
}
freeaddrinfo(res); // free the linked list
return count;
}
int setnonblock (int fd) {
int flags;
int n;
flags = fcntl(fd, F_GETFL);
//O_NONBLOCK=0x4000
fcntl(fd, F_SETFL, flags | O_NONBLOCK);
n= fcntl(fd, F_GETFL) & O_NONBLOCK;
return n;
}
int setblock (int fd) {
int flags;
int n;
flags = fcntl(fd, F_GETFL);
fcntl(fd, F_SETFL, flags & ~O_NONBLOCK);
n= fcntl(fd, F_GETFL) & O_NONBLOCK;
return n;
}
int connecttcp(char *ip,int port,int msecs){
//EAGAIN,
//EINTR:The system call was interrupted by a signal that was caught;
int sockfd;
struct sockaddr_in server_addr;
socklen_t addrlen;
int ret;
int n;
fd_set rfds,wfds;
struct timeval tv;
//int msecs=1000;
int retval;
int ok=0;
int tryconnect=0;
if((sockfd = socket(PF_INET, SOCK_STREAM, 0))<0){
perror("socket()");
exit(EXIT_FAILURE);
}
setnonblock(sockfd);
memset(&server_addr,0, sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(port);
server_addr.sin_addr.s_addr = inet_addr(ip);
addrlen=sizeof(server_addr);
n=1;
do{
FD_ZERO(&wfds);
FD_SET(sockfd, &wfds);
tv.tv_sec = msecs/1000;
tv.tv_usec =(tv.tv_sec*1000-msecs)*1000;
retval = select(sockfd+1,NULL,&wfds, NULL, &tv);//for writing
tryconnect++;
//printf("retval=%d",retval);
errno=0;
ret=connect(sockfd, (struct sockaddr *)&server_addr,addrlen);
if(ret<0){
//sleep(1);
perror("connect");
debugerr(fprintf(stderr,"errno=%d, EINPROGRESS=%d,EISCONN=%d\n",errno,EINPROGRESS,EISCONN));
//connect: Operation now in progress
//retval=1errno=119, 119
//EINPROGRESS
//EISCONN =127
//Need select
if(errno == EISCONN){
ok=!0;
break;
}
if (errno == EINTR){
continue;
}
if (errno == EAGAIN ||errno==EINPROGRESS){
continue;
}
if (errno == ECONNREFUSED){
ok=0;
break;
}
}else {
ok=!0;
break;
}
if(tryconnect >TRY){
ok=0;
break;
}
}while(n>0);
if(ok){
setblock(sockfd);
debugerr(fprintf(stderr,"Connect to %s port %d, fd=%d\n",ip,port,sockfd));
return sockfd;
}
close(sockfd);
debugerr(fprintf(stderr,"Cannot connect to %s port %d! close fd=%d \n",ip,port,sockfd));
return 0;
}
int main(int argc,char *argv[])
{
int fd;
//char buf[128]="GET /demox.html?ip=31.31.520.99&name=Sugar31 HTTP/1.1\r\nHost: 127.0.0.1:9999\r\n\r\n\r\n";
char buf[128]="GET /index.html?ip=31.31.520.99&name=Sugar31 HTTP/1.1\r\nHost: 127.0.0.1:9999\r\n\r\n\r\n";
char ret[1204];
int n;
char ipv4[INET6_ADDRSTRLEN];
char *ip="127.0.0.1";
int port=80;
int msec=1000;
if(argc<2){
printf("usage: %s hostname \n",argv[0]);
exit(EXIT_FAILURE );
}
printf("%s %s\n",argv[0],argv[1]);
getaddr(argv[1],ipv4,NULL);
printf("Connect to %s:%d [msec:%d] and\nSend:\n%s\n",ipv4,port,msec,buf);
fd=connecttcp(ipv4,port,msec);
// setnonblock(fd);
//setblock(fd);
if(fd>0){
write(fd,buf,strlen(buf));
do{
memset(ret,0,sizeof(ret));
n=read(fd,ret,sizeof(ret)-1);
if(n>0){
ret[n]=0;
printf("--->%s\n",ret);
}else break;
}while(n>0);
printf("close connection\n");
//sleep(10);
close(fd);
exit(EXIT_SUCCESS);
}
exit(EXIT_FAILURE );
}
Authors: WhoAmI, CrazyMonkeyemail: kccddb@gmail.comDate: 20221217Copyright: CC BY-NC-SA
Jun 22, 2025Author: \mathcal{CrazyDog}, Ph.D. in Electrical Engineering, NCTUemail: kccddb@gmail.comDate: 20230910
Jun 22, 2025Authors: CrazyDog, CrazyMonkeyemail: kccddb@gmail.comDate: 20230222
Jun 22, 2025Author: WhoAmI Date: 20230523 email:kccddb@gmail.com Copyright: CC BY-NC-SA 《荀子‧勸學》不積跬步,無以至千里;不積小流,無以成江海。 I. Mutex variables MUST be declared with type pthread_mutex_t, and must be initialized before they can be used. II. 了解 pthread_mutex_lock / pthread_mutex_unlock 與可能問題和代價 III. 程式執行效率與startvation 等問題
Jul 11, 2024or
By clicking below, you agree to our terms of service.
New to HackMD? Sign up