REUSEADDR,服务器连接多个客户端,点对点聊天程序
来源:互联网 发布:小米主题 windows xp 编辑:程序博客网 时间:2024/06/13 07:04
1. REUSEADDR
在绑定地址端口之前尽可能调用setsocktopt()来设置REUSEADDR套接字选项
使用了REUSEADDR选项后,可以使得不必等待TIME_WAIT状态消失就可以重启服务器
//设置REUSEADDR 选项 int on = 1; run = setsockopt(listenfd,SOL_SOCKET,SO_REUSEADDR,&on,sizeof(on)); if(run < 0) { printf("error setsokopt \n"); return -5; }
2.服务器连接多个客户端
使用多进程进行处理,用子进程处理链接
父进程继续处理accept();从完成链接队列中再获取一个
服务器端有两个套接字,一个已连接套接口,主要是用来通信的
一个监听调节口,主要实现三次握手的过程
客户端只有一个套接字,链接套接字
//服务器端函数#include<stdio.h>#include<sys/socket.h>#include<netinet/in.h>#include<arpa/inet.h>#include<string.h>#include<stdlib.h>void do_service(int conn){ //实现回射通信 char recvbuf[1024]; while(1) { memset(recvbuf,0,sizeof(recvbuf));int ret=0;//接受客户端的请求,read()失败返回-1 ret = read(conn,recvbuf,sizeof(recvbuf)); //返回实际接受到的字节数 if(ret == 0) //说明客户端关闭了 { printf("client close \n"); break; } else if(ret == -1) //-1表示失败了 { printf("error read() \n"); break; }//对请求进行处理printf("%s",recvbuf);//对客户端进行数据应答 write(conn,recvbuf,ret); }}int main(){ int listenfd; int run; //首先调用socket()函数创建套接字 listenfd =socket(PF_INET,SOCK_STREAM,IPPROTO_TCP); //在LINUX 下可以用man socket 查询该函数的具体描述 if(listenfd < 0) {printf("ERROR\n");return -1; } struct sockaddr_in servaddr; //IPV4的地址结构 memset(&servaddr,0,sizeof(servaddr)); // 初始化地址 servaddr.sin_family = AF_INET; //地址的家族 servaddr.sin_port = htons(5188); //端口号,2个字节,这里需要的是网络字节序(大端),需要将5188转换为网络字节序 servaddr.sin_addr.s_addr = htonl(INADDR_ANY); //设置地址,INADDR_ANY表示本地的任意地址 //设置REUSEADDR 选项 int on = 1; run = setsockopt(listenfd,SOL_SOCKET,SO_REUSEADDR,&on,sizeof(on)); if(run < 0) { printf("error setsokopt \n"); return -5; } //第二步为套接字绑定一个本地地址 run=bind(listenfd,(struct sockaddr *)&servaddr,sizeof(servaddr)); if(run < 0) {printf("error\n"); return -2; } //第三步:使套接字处于监听状态 run = listen(listenfd,SOMAXCONN); if(run < 0) { printf("error\n"); return -3; } struct sockaddr_in peeraddr; //定义对方的地址 socklen_t peerlen =sizeof(peeraddr); //定义对方的地址长度大小,注意需要有初始值,负责 accept()会失败 int conn; pid_t pid; //第四步:从已完成连接队列中返回第一个连接,如果没有连接过来一直处于阻塞状态 while(1) { conn = accept(listenfd,(struct sockaddr *)&peeraddr,&peerlen); if(conn < 0) {printf("error\n");return -4; } //如果连接成功可以将对方的连接地址打印出来 printf("ip= %s ,port=%d \n",inet_ntoa(peeraddr.sin_addr),ntohs(peeraddr.sin_port)); //创建进程 pid = fork();if(pid == -1) // 失败{ printf("error fork()\n"); return -1;} if(pid == 0) //fork()为子进程返回0 { close(listenfd); //子进程不需要处理监听,只需要处理链接 do_service(conn); //服务器相应函数 exit(EXIT_SUCCESS);}else //为父进程返回非负整数 { close(conn); //父进程不需要处理链接,关闭链接套接口 } } return 0;}
3. 点对点聊天程序
在服务器端/客户端创建一个线程专门用来从键盘上获取字符,发送到客户端
另外一个进程专门用来进行接受字符
//服务器端函数#include<stdio.h>#include<sys/socket.h>#include<netinet/in.h>#include<arpa/inet.h>#include<string.h>#include<stdlib.h>#include<errno.h>#include<signal.h>void handler(int sig){ printf("recv a sig = %d\n",sig); printf("服务器端子进程退出\n"); exit(0);}int main(){ int listenfd; int run; extern int errno; //首先调用socket()函数创建套接字 listenfd =socket(PF_INET,SOCK_STREAM,IPPROTO_TCP); //在LINUX 下可以用man socket 查询该函数的具体描述 if(listenfd < 0) {printf("ERROR\n");return -1; } struct sockaddr_in servaddr; //IPV4的地址结构 memset(&servaddr,0,sizeof(servaddr)); // 初始化地址 servaddr.sin_family = AF_INET; //地址的家族 servaddr.sin_port = htons(5188); //端口号,2个字节,这里需要的是网络字节序(大端),需要将5188转换为网络字节序 servaddr.sin_addr.s_addr = htonl(INADDR_ANY); //设置地址,INADDR_ANY表示本地的任意地址 //设置REUSEADDR 选项 int on = 1; run = setsockopt(listenfd,SOL_SOCKET,SO_REUSEADDR,&on,sizeof(on)); if(run < 0) { printf("error setsokopt \n"); return -5; } //第二步为套接字绑定一个本地地址 run=bind(listenfd,(struct sockaddr *)&servaddr,sizeof(servaddr)); if(run < 0) {printf("error\n"); return -2; } //第三步:使套接字处于监听状态 run = listen(listenfd,SOMAXCONN); if(run < 0) { printf("error\n"); return -3; } struct sockaddr_in peeraddr; //定义对方的地址 socklen_t peerlen =sizeof(peeraddr); //定义对方的地址长度大小,注意需要有初始值,负责 accept()会失败 int conn; pid_t pid; //第四步:从已完成连接队列中返回第一个连接,如果没有连接过来一直处于阻塞状态 conn = accept(listenfd,(struct sockaddr *)&peeraddr,&peerlen); if(conn < 0) {printf("error\n");return -4; } //如果连接成功可以将对方的连接地址打印出来 printf("ip= %s ,port=%d \n",inet_ntoa(peeraddr.sin_addr),ntohs(peeraddr.sin_port)); //创建进程 pid = fork(); if(pid == -1) // 失败 { printf("error fork()\n");return -1; } if(pid == 0) //fork()为子进程返回0,专门用来发送数据 { close(listenfd); //子进程不需要处理监听,只需要处理链接 int writeerro; char sendbuff[1024]; signal(SIGUSR1,handler); //信号处理函数,当收到这个信号时,调用信号处理函数 while( fgets(sendbuff,sizeof(sendbuff),stdin)!=NULL) { writeerro=write(conn,sendbuff,strlen(sendbuff)); memset(sendbuff,0,sizeof(sendbuff)); } } else //为父进程返回非负整数,专门用来接受数据 { char recvbuff[1024]; while(1) { memset(recvbuff,0,sizeof(recvbuff)); int ret = read(conn,recvbuff,sizeof(recvbuff)); if(ret == -1) { printf("error read \n"); break; } else if(ret == 0) { printf("peer close \n"); break; } fputs(recvbuff,stdout); } kill(pid,SIGUSR1);//当父进程退出时向子进程发送SIGUSR1信号 printf("服务器端父进程退出\n"); close(conn); exit(0); } return 0;}
//客户端程序
#include<stdio.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<string.h>
#include<stdlib.h>
int main()
{
int sock;
int error=0;
//第一步 创建客户端套接字
sock=socket(PF_INET,SOCK_STREAM,IPPROTO_TCP);
if(sock < 0)
{
printf("error socket();\n");
return -1;
}
//设置连接地址
struct sockaddr_in client;
memset(&client,0,sizeof(client));
client.sin_family=AF_INET;
client.sin_port=htons(5188);
client.sin_addr.s_addr =inet_addr("127.0.0.1");
//客户端发起连接
error=connect(sock,(struct sockaddr *)&client,sizeof(client));
if(error<0)
{
printf("error connect();%d\n",error);
return -2;
}
pid_t pid;
pid = fork();
if(pid == -1)
{
printf("error fork \n");
return -1;
}
else if(pid == 0) //子进程返回0,专门用来接收数据
{
char recvbuff[1024];
while(1)
{
memset(recvbuff,0,sizeof(recvbuff));
int ret = read(sock,recvbuff,sizeof(recvbuff));
if(ret == -1)
{
printf("error read \n");
}
else if(ret == 0)
{
printf("peer close \n");
break;
}
fputs(recvbuff,stdout);
}
printf("客户端子进程退出\n");
exit(0);
}
else //为父进程返回非负整数,专门用来发送数据
{
char sendbuff[1024];
while( fgets(sendbuff,sizeof(sendbuff),stdin)!=NULL)
{
write(sock,sendbuff,strlen(sendbuff));
memset(sendbuff,0,sizeof(sendbuff));
}
close(sock);
printf("客户端父进程退出\n");
}
return 0;
}
阅读全文
0 0
- REUSEADDR,服务器连接多个客户端,点对点聊天程序
- Java实现多个客户端聊天程序
- Java实现多个客户端聊天程序
- Unix网络编程之点对点聊天-客户端与服务器实现
- 点对点聊天程序
- 设计点对点聊天程序
- netty 点对点聊天程序
- 多客户端聊天程序
- C# Socket聊天程序(一个服务端,多个客户端)
- C# Socket聊天程序(一个服务端,多个客户端)
- TCP服务器接收多个客户端连接
- TCP的多个客户端连接服务器
- 最近用VB.NET做了一个多人聊天程序,但是只能连接两个客户端,不知是何意?连接第三个客户端时ListenThread侦听线程好象没反应,但是客户端软件提示连接成功!
- C#.net udp点对点聊天程序
- MFC实现简单点对点聊天程序
- socket编程之点对点聊天程序
- socket实现多个客户端连接在一个服务器上
- python 可连接多个客户端的服务器 fork版
- Happy 2004
- 数据类型(1)类型定义
- 大话程序猿眼里的高并发架构
- openpose的细节处理
- 3-8·Linux源码包管理、脚本安装包
- REUSEADDR,服务器连接多个客户端,点对点聊天程序
- xmos_helloworld
- java字符串所有组合,字符串全组合--递归
- 数据结构实验之排序四:寻找大富翁
- Sicily1000. 词法分析
- VMware中centOS配置静态IP
- Python基础-多进程-线程池Pool-进程间通信
- Echarts实现可视化世界地图——Vue
- 史上最强屏幕适配方案,傻瓜式集成,一步到位---不服来辩!