文章版权归原作者所有! (www.MegaEntry.com)
-------------------------------------------------------------------------------- Client int sock_connect(char *domain,int port) { int white_sock; struct hostent * site; struct sockaddr_in me; site = gethostbyname(domain); if (site==NULL) return -2; white_sock = socket(AF_INET,SOCK_STREAM,0); if (white_sock<0) return -1; memset(&me,0,sizeof(struct sockaddr_in));文章版权归原作者所有! (www.MegaEntry.com)
memcpy(&me.sin_addr,site->h_addr_list[0],site->h_length); me.sin_family = AF_INET; me.sin_port = htons(port); return (connect(white_sock,(struct sockaddr *)&me,sizeof(struct sockaddr))<0) ? -1 : white_sock; } 要由Client向伺服器端要求连线的步骤,首先您必须要找出对方的位址,可利用: gethostbyname() 接下来要建立起一个socket,然後用这个socket来建立连线。 接下来我们利用这个简单的socket程式来写一个读取WWW网页的简单浏览器(看html source)。 #include文章版权归原作者所有! (www.MegaEntry.com)
#includeMegaEntry 网络社区与信息交流平台!
white_sock = socket(AF_INET,SOCK_STREAM,0); if (white_sock<0) return -1; memset(&me,0,sizeof(struct sockaddr_in)); memcpy(&me.sin_addr,site->h_addr_list[0],site->h_length); me.sin_family = AF_INET; me.sin_port = htons(port); return (connect(white_sock,(struct sockaddr *)&me,sizeof(struct sockaddr))<0) ? -1 : white_sock; } int htsend(int sock,char *fmt,...) { char BUF[1024]; va_list argptr; va_start(argptr,fmt);MegaEntry 网络社区与信息交流平台!
vsprintf(BUF,fmt,argptr); va_end(argptr); return send(sock,BUF,strlen(BUF),0); } void main(int argc,char **argv) { int black_sock; char bugs_bunny[3]; if (argc<2) return; black_sock = htconnect(argv[1],80); if (black_sock<0) return; htsend(black_sock, "GET / HTTP/1.0%c ",10); htsend(black_sock, "Host: %s%c ",argv[1],10);文章版权归原作者所有! (www.MegaEntry.com)
htsend(black_sock, "%c ",10); while (read(black_sock,bugs_bunny,1)>0) { printf( "%c ",bugs_bunny[0]); } close(black_sock); } 编译: gcc -o ex1 client.c 执行 ./ex1 www.linux.org.tw -------------------------------------------------------------------------------- Server Listen to a portMegaEntry 网络社区与信息交流平台!
要建立起一个网路伺服器,第一步就是要 "倾远方 ",也就是要Listen。 以下是一般建立服务的方法: int DaemonSocket; struct sockaddr_in DaemonAddr; int BindSocket(void) { DaemonSocket = socket(AF_INET,SOCK_STREAM,0); if (DaemonSocket==-1) return 0; DaemonAddr.sin_family = AF_INET; DaemonAddr.sin_port = htons(DAEMON_PORT); if (bind(DaemonSocket,&DaemonAddr,sizeof(DaemonAddr))<0) { printf( "Can not bind! "); return 0; } if (listen(DaemonSocket,1024)!=0) {MegaEntry 网络社区与信息交流平台!
printf( "Can not listen! "); return 0; } return 1; } Incoming call 要查看是否有连线进来,可用以下方式: int incoming_call(void) { fd_set sock; struct timeval tv; int t; FD_ZERO(&sock);文章版权归原作者所有! (www.MegaEntry.com)
FD_SET(DaemonSocket,&sock); tv.tv_sec = 60; tv.tv_usec = 0; t = select(DaemonSocket + 1,&sock,NULL,NULL,&tv); if (t<=0||!FD_ISSET(DaemonSocket,&sock)) return 0; printf( "incoming... "); return 1; } Connect Client 当我们确认有人进来要求服务时,会需要accept connection,可用以下方式 int ConnectClient(void) { int socksize=sizeof(HostAddr); unsigned char * addr;文章版权归原作者所有! (www.MegaEntry.com)
ClientSocket = accept(DaemonSocket,(struct sockaddr*)&HostAddr,&socksize); if (ClientSocket<0) return 0; addr = (unsigned char *)&HostAddr.sin_addr.s_addr; printf( "incoming address:%d.%d.%d.%d ",addr[0],addr[1],addr[2],addr[3]); return 1; } 注意到当您accept connection之後,连线已建立起,此时要用的socket是ClientSocket,而非DaemonSocket,ClientSocket才是真正用来连线用的socket。 这是个我才刚开始动手写的象棋伺服器。 #includeMegaEntry 网络社区与信息交流平台!
#includeMegaEntry 网络社区与信息交流平台!
int DaemonSocket; struct sockaddr_in DaemonAddr; int ClientSocket=0; struct sockaddr_in HostAddr; void dlog(char *fmt,...) { va_list argptr; FILE *fp; fp = fopen(DAEMON_LOG, "a+t "); va_start(argptr,fmt); vfprintf(fp,fmt,argptr); va_end(argptr); fclose(fp);MegaEntry 网络社区与信息交流平台!
} pid_t CheckLock(void) { pid_t me; FILE * fp; fp = fopen(DAEMON_LOCK, "rt "); if (fp==NULL) return 0; fscanf(fp, "%d ",&me); fclose(fp); return me; } pid_t WriteLock(void)文章版权归原作者所有! (www.MegaEntry.com)
{ pid_t me; FILE *fp; me = getpid(); fp = fopen(DAEMON_LOCK, "w "); fprintf(fp, "%d ",me); fclose(fp); return me; } int CleanLock(void) { return (unlink(DAEMON_LOCK)==0);MegaEntry 网络社区与信息交流平台!
} void report_time(void) { time_t now; now = time(NULL); dlog( "%s ",asctime((const struct tm*)localtime(&now))); } static void signal_catch(int signo) { time_t now; close(DaemonSocket); if (ClientSocket>0) close(ClientSocket); CleanLock();MegaEntry 网络社区与信息交流平台!
now = time(NULL); dlog( "Catch signal %d, leave at %s ",signo,asctime((const struct tm*)localti exit(-1); } void SetupSignal(void) { struct sigaction act; act.sa_handler = signal_catch; act.sa_flags = 0; sigemptyset(&act.sa_mask); sigaction(SIGHUP,&act,NULL); sigaction(SIGINT,&act,NULL); sigaction(SIGQUIT,&act,NULL); sigaction(SIGILL,&act,NULL);文章版权归原作者所有! (www.MegaEntry.com)
sigaction(SIGABRT,&act,NULL); sigaction(SIGIOT,&act,NULL); sigaction(SIGBUS,&act,NULL); sigaction(SIGFPE,&act,NULL); sigaction(SIGTERM,&act,NULL); } int BindSocket(void) { DaemonSocket = socket(AF_INET,SOCK_STREAM,0); if (DaemonSocket==-1) return 0; DaemonAddr.sin_family = AF_INET; DaemonAddr.sin_port = htons(DAEMON_PORT); if (bind(DaemonSocket,&DaemonAddr,sizeof(DaemonAddr))<0) { printf( "Can not bind! ");文章版权归原作者所有! (www.MegaEntry.com)
return 0; } if (listen(DaemonSocket,1024)!=0) { printf( "Can not listen! "); return 0; } return 1; } int incoming_call(void) { fd_set sock; struct timeval tv; int t;文章版权归原作者所有! (www.MegaEntry.com)
FD_ZERO(&sock); FD_SET(DaemonSocket,&sock); tv.tv_sec = 60; tv.tv_usec = 0; t = select(DaemonSocket + 1,&sock,NULL,NULL,&tv); if (t<=0||!FD_ISSET(DaemonSocket,&sock)) return 0; dlog( "incoming... "); return 1; } int ConnectClient(void) { int socksize=sizeof(HostAddr); unsigned char * addr;MegaEntry 网络社区与信息交流平台!
ClientSocket = accept(DaemonSocket,(struct sockaddr*)&HostAddr,&socksize); if (ClientSocket<0) return 0; addr = (unsigned char *)&HostAddr.sin_addr.s_addr; dlog( "incoming address:%d.%d.%d.%d ",addr[0],addr[1],addr[2],addr[3]); return 1; } int daemon_printf(char *fmt,...) { char BUF[4096]; va_list argptr; va_start(argptr,fmt);MegaEntry 网络社区与信息交流平台!
vsprintf(BUF,fmt,argptr); va_end(argptr); return write(ClientSocket,BUF,strlen(BUF)); } void Log(void) { char BUF[4096]; read(DaemonSocket,BUF,16); daemon_printf( "%s ",BUF[0]); } int main(int argc,char **argv) { pid_t myself; time_t now;MegaEntry 网络社区与信息交流平台!
/* find myself */ myself = CheckLock(); if (myself!=0) { printf( "Existing a copy of chess daemon[pid=%d], leave now. ",myself); exit(1); } /* fork */ myself = fork(); if (myself>0) { exit(1); } else if (myself<0) { printf( "Strange world! I don 't like it. Quit because of pid=%d ",myself); exit(1);文章版权归原作者所有! (www.MegaEntry.com)
} else { SetupSignal(); if (!BindSocket()) { printf( "Can not bind socket! "); exit(1); } WriteLock(); } printf( "Chess Daemon is up, have fun! "); now = time(NULL); dlog( "---------------------------------------------- "); dlog( "I am back! %s "MegaEntry 网络社区与信息交流平台!
"Chess Daemon comes to alive again. ", asctime((const struct tm*)localtime(&now)) ); do { if (incoming_call()) { if (ConnectClient()) { fd_set sock; struct timeval tv; int t; char BUF[128]; char CC[2]; int n;MegaEntry 网络社区与信息交流平台!
daemon_printf( "Welcome to Chinese Chess Game Center! "); FD_ZERO(&sock); FD_SET(ClientSocket,&sock); n = 0; do { tv.tv_sec = 60; tv.tv_usec = 0; t = select(ClientSocket+1,&sock,NULL,NULL,&tv); if (t<=0||!FD_ISSET(ClientSocket,&sock)) ; read(ClientSocket,CC,1); if (CC[0]==13||CC[0]==10||CC[0]==0) { BUF[n] = 0; dlog( "%s ",BUF); if (strncasecmp(BUF, "exit ",4)==0) { close(ClientSocket); break;MegaEntry 网络社区与信息交流平台!
} n = 0; } else { BUF[n]=CC[0]; n++; } } while (1); } } } while (1); return 1; } 检验 telnet localhost 9901文章版权归原作者所有! (www.MegaEntry.com)
在处理Connect Client时,事实上可以运用fork或thread来处理多个连线。