socket(三)
来源:互联网 发布:mac eclipse gbk 编辑:程序博客网 时间:2024/06/05 19:07
一、REUSEADDR
服务器端关闭,再重新启动时又要去重新绑定地址,但此时网络仍处于TIME_WAIT状态,无法重新绑定。解决的办法就是服务器在绑定前调用setsockopt来设置REUSEADDR套接字选项。它可以使不必等待TIME_WAIT状态消失就可以重启服务器。
int on=1;if(setsockopt(listenfd,SOL_SOCKET,SO_REUSEADDR,&on,sizeof(on))<0) ERROR_EXIT("setsockopt");
二、点对点的聊天程序
服务器端:
#include <unistd.h>#include <sys/types.h>#include <sys/socket.h>#include <netinet/in.h>#include <arpa/inet.h>#include <stdlib.h>#include <stdio.h>#include <errno.h>#include <string.h>#define ERR_EXIT(m) \ do \ { \perror(m); \exit(EXIT_FAILURE); \ } while(0)int main(void){int listenfd;if((listenfd=socket(AF_INET,SOCK_STREAM,0))<0)ERR_EXIT("socket");struct sockaddr_in addr;memset(&addr,0,sizeof(addr));addr.sin_family=AF_INET;addr.sin_port=htons(5188);addr.sin_addr.s_addr=htonl(INADDR_ANY); /*addr.sin_addr.s_addr=inet_addr(127.0.0.1); inet_aton("127.0.0.1",&addr.sin_addr);*/int on=1;if(setsockopt(listenfd,SOL_SOCKET,SO_REUSEADDR,&on,sizeof(on))<0)ERR_EXIT("setsockopt");if(bind(listenfd,(struct sockaddr*)&addr,sizeof(addr))<0)ERR_EXIT("bind");if(listen(listenfd,SOMAXCONN)<0)ERR_EXIT("listen");struct sockaddr_in peeraddr;socklen_t peerlen=sizeof(peeraddr);int conn;if((conn=accept(listenfd,(struct sockaddr*)&peeraddr,&peerlen))<0)ERR_EXIT("accept");printf("ip=%s port=%d\n", inet_ntoa(peeraddr.sin_addr),ntohs(peeraddr.sin_port)); pid_t pid;pid=fork();if(pid==-1)ERR_EXIT("fork");if(pid==0){char sendbuf[1024];while(fgets(sendbuf,sizeof(sendbuf),stdin)!=NULL){write(conn,sendbuf,strlen(sendbuf));memset(sendbuf,0,sizeof(sendbuf));}exit(EXIT_SUCCESS);}else{char recvbuf[1024];while (1){memset(recvbuf,0,sizeof(recvbuf));int ret=read(conn,recvbuf,sizeof(recvbuf));if (ret==-1){ERR_EXIT("read");}else if(ret==0){printf("peer close\n");break;}fputs(recvbuf,stdout);}exit(EXIT_SUCCESS);}close(listenfd);close(conn);return 0;}客户端:
#include <unistd.h>#include <sys/types.h>#include <sys/socket.h>#include <netinet/in.h>#include <arpa/inet.h>#include <stdlib.h>#include <stdio.h>#include <errno.h>#include <string.h>#define ERR_EXIT(m) \ do \ { \perror(m); \exit(EXIT_FAILURE); \ } while(0)int main(void){int sock;if((sock=socket(AF_INET,SOCK_STREAM,0))<0)ERR_EXIT("socket");struct sockaddr_in servaddr;memset(&servaddr,0,sizeof(servaddr));servaddr.sin_family=AF_INET;servaddr.sin_port=htons(5188);servaddr.sin_addr.s_addr=inet_addr("127.0.0.1"); /*addr.sin_addr.s_addr=inet_addr(127.0.0.1); inet_aton("127.0.0.1",&addr.sin_addr);*/if(connect(sock,(struct sockaddr*)&servaddr,sizeof(servaddr))<0)ERR_EXIT("connect");pid_t pid;pid=fork();if(pid==-1)ERR_EXIT("fork");if(pid==0){char sendbuf[1024];while(fgets(sendbuf,sizeof(sendbuf),stdin)!=NULL){write(sock,sendbuf,strlen(sendbuf));memset(sendbuf,0,sizeof(sendbuf));}exit(EXIT_SUCCESS);}else{char recvbuf[1024];while (1){memset(recvbuf,0,sizeof(recvbuf));int ret=read(sock,recvbuf,sizeof(recvbuf));if (ret==-1){ERR_EXIT("read");}else if(ret==0){printf("peer close\n");break;}fputs(recvbuf,stdout);}exit(EXIT_SUCCESS);}close(sock);return 0;}
三、上述程序中存在的问题
上述代码客户端和服务器都使用子进程处理输入,而父进程处理从对方接受数据,当接受数据大小为0时,父进程退出。实际上子进程仍在残留,可以使用信号的方法通知子进程,子进程收到信号后退出。这是用信号的方式进程进程间通信。
#include <signal.h>void handler(int sig){printf("recv a sig=%d\n",sig);exit(EXIT_SUCCESS);}signal(SIGUSR1,handler);//子进程中kill(pid, STGUR1);//父进程中/*子进程通知父进程signal(SIGUSR1,handler);kill(getppid(), STGUR1);*/
0 0
- socket编程(三)
- socket(三)
- Socket客户端(三)
- socket编程(三)
- socket编程(三)
- C++ Socket(三)
- Java Socket编程(三)
- Java Socket编程(三)
- Linux Socket学习(三)
- Linux Socket学习(三)
- Linux Socket学习(三)
- Java socket编程(三)
- Java(三) Socket编程
- socket select模型(三)
- socket 编程基础(三)
- linux socket 编程(三)
- Java Socket 通信 (三)
- Socket 基础编程(三)
- Linux软件安装方式
- HDU 3613 Best Reward (manacher)
- Java:重写equals()和hashCode()
- 注意Java代码的内存泄漏
- word pattern
- socket(三)
- 挂载光驱
- 面向对象与面向过程
- U-Boot的加载地址分析
- 手把手教你ARC——iOS/Mac开发ARC入门和使用
- Core Data
- JAVA list
- 后端分布式系列:分布式存储-MySQL 数据库事务与复制
- FTP服务器连接出现500错误