使用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;
}