使用socket编程(一) 中的主程序,存在以下两个问题:
1). 有时候重启会出错,提示“bind error: Address already in use”。解决此问题用到setsockopt()函数;
2). 同时只能处理单用户请求;
下面进一步完善”socket编程(一)“的主程序,使用它能同时处理多个客户端请求。
主要技巧是使用fork()产生子进程,让子进程去处理客户端请求。
#include "../apue.h"
int main(void){ int listenfd; listenfd=socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if(listenfd < 0) err_exit("listen error"); struct sockaddr_in servaddr; memset(&servaddr, 0, sizeof(servaddr)); servaddr.sin_family = AF_INET; servaddr.sin_port = htons(5188); servaddr.sin_addr.s_addr = htonl(INADDR_ANY); //servaddr.sin_addr.s_addr = inet_addr("127.0.0.1"); //inet_aton("127.0.0.1", $servaddr.sin_addr); int on=1; if(setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on))<0) err_exit("setsockopt error"); if(bind(listenfd, (struct sockaddr*)&servaddr, sizeof(servaddr))<0) err_exit("bind error"); if(listen(listenfd, SOMAXCONN)<0) err_exit("listen error"); struct sockaddr_in peeraddr; socklen_t peerlen = sizeof(peeraddr); int conn; pid_t pid; while (1){ if((conn = accept(listenfd, (struct sockaddr*)&peeraddr, &peerlen))<0) err_exit("accept error"); printf("ip=%s,port=%d\n", inet_ntoa(peeraddr.sin_addr), peeraddr.sin_port); pid = fork(); if(pid==-1) err_exit("fork error"); if(pid==0){ close(listenfd); while(1){ char buf[1024]; int ret; memset(buf, 0, sizeof(buf)); ret = read(conn, buf, sizeof(buf)); if(ret==0){ printf("client close\n"); break; } else if(ret==-1) err_exit("ret error"); fputs(buf, stdout); write(conn, buf, ret); } exit(EXIT_SUCCESS); }else{ close(conn); } } return 0; }