热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

socket编程第三节(处理多客户连接)

之前socket编程第二节中客户端和服务器链接有个问题,那就是一旦服务器断开链接客户端是无法再重新链接的。因为服务器是没办法绑定成功的。所以需要REUSEADDR进

 之前socket编程第二节中客户端和服务器链接有个问题,那就是一旦服务器断开链接客户端是无法再重新链接的。因为服务器是没办法绑定成功的。

所以需要REUSEADDR进行设置。

只要在上一节加上这几行代码就可以了。

 

 如何处理多客户端并发

思想就是创建一个子进程,让子进程执行打印,父进程执行链接。

修改服务器端的代码:(代码注释可以参考上一节)客户端代码不需要动。执行两次就可以看到有连个客户端与一个服务器链接。

#include
#include
#include
#include
#include
#include
#include
#include
#include #define ERR_EXIT(m) \do \{ \perror(m); \exit(EXIT_FAILURE); \}while(0)void do_server(int conn);
int main()
{int listenfd;if((listenfd &#61; socket(PF_INET,SOCK_STREAM,IPPROTO_TCP)) <0){ERR_EXIT("socket");}struct sockaddr_in servaddr;memset(&servaddr,0,sizeof(servaddr));servaddr.sin_family &#61; AF_INET;servaddr.sin_port &#61; htons(5188);servaddr.sin_addr.s_addr &#61; htonl(INADDR_ANY);int on &#61; 1;if(setsockopt(listenfd,SOL_SOCKET,SO_REUSEADDR,&on,sizeof(on)) <0){ERR_EXIT("setsockopt");}if(bind(listenfd,(struct sockaddr*)&servaddr,sizeof(servaddr)) <0){ERR_EXIT("bind");}if(listen(listenfd,SOMAXCONN) <0){ERR_EXIT("listen");}int conn; struct sockaddr_in peeraddr;socklen_t peerlen &#61; sizeof(peeraddr);while(1) //循环执行父进程执行链接套接字{if((conn &#61; accept(listenfd,(struct sockaddr*)&peeraddr,&peerlen)) <0){ERR_EXIT("accept");}printf("ip &#61; %s port &#61; %d\n",inet_ntoa(peeraddr.sin_addr),ntohs(peeraddr.sin_port));pid_t pid &#61; fork();if(pid &#61;&#61; -1){ERR_EXIT("fork");}if(pid &#61;&#61; 0)//子进程执行操作{close(listenfd);do_server(conn);}else{close(conn);}}return 0;}void do_server(int conn)
{char recvbuf[1024];while(1){memset(recvbuf,0,sizeof(recvbuf));int ret &#61; read(conn,recvbuf,sizeof(recvbuf));fputs(recvbuf,stdout);write(conn,recvbuf,ret);}close(conn);
}

运行结果&#xff1a;

 

 

实现一个客户端关闭&#xff0c;服务器端捕捉到客户端关闭&#xff1a;

#include
#include
#include
#include
#include
#include
#include
#include
#include #define ERR_EXIT(m) \do \{ \perror(m); \exit(EXIT_FAILURE); \}while(0)void do_server(int conn);
int main()
{int listenfd;if((listenfd &#61; socket(PF_INET,SOCK_STREAM,IPPROTO_TCP)) <0){ERR_EXIT("socket");}struct sockaddr_in servaddr;memset(&servaddr,0,sizeof(servaddr));servaddr.sin_family &#61; AF_INET;servaddr.sin_port &#61; htons(5188);servaddr.sin_addr.s_addr &#61; htonl(INADDR_ANY);int on &#61; 1;if(setsockopt(listenfd,SOL_SOCKET,SO_REUSEADDR,&on,sizeof(on)) <0){ERR_EXIT("setsockopt");}if(bind(listenfd,(struct sockaddr*)&servaddr,sizeof(servaddr)) <0){ERR_EXIT("bind");}if(listen(listenfd,SOMAXCONN) <0){ERR_EXIT("listen");}int conn; struct sockaddr_in peeraddr;socklen_t peerlen &#61; sizeof(peeraddr);while(1) //循环执行父进程执行链接套接字{if((conn &#61; accept(listenfd,(struct sockaddr*)&peeraddr,&peerlen)) <0){ERR_EXIT("accept");}printf("ip &#61; %s port &#61; %d\n",inet_ntoa(peeraddr.sin_addr),ntohs(peeraddr.sin_port));pid_t pid &#61; fork();//只要有一个客户端链接就创建一个进程//假如有三个客户端链接其实是有4个进程的if(pid &#61;&#61; -1){ERR_EXIT("fork");}if(pid &#61;&#61; 0)//子进程执行操作{close(listenfd);do_server(conn);exit(EXIT_SUCCESS);//当客户端关闭了&#xff0c;子进程就应该销毁了&#xff0c;否则子进程也会执行父进程的代码}else{close(conn);}}return 0;}void do_server(int conn)
{char recvbuf[1024];while(1){memset(recvbuf,0,sizeof(recvbuf));int ret &#61; read(conn,recvbuf,sizeof(recvbuf));if(ret &#61;&#61; 0){printf("client close\n");break;}else if (ret &#61;&#61; -1){ERR_EXIT("read");}fputs(recvbuf,stdout);write(conn,recvbuf,ret);}close(conn);
}

执行结果&#xff1a;

 

 

实现一个点对点通信

实现的思路是服务器和客户端分辨创建一个子进程。子进程接收键盘的信息并且发送信息&#xff0c;父进程负责接收信息并且显示出来。

服务器代码&#xff1a;

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define ERR_EXIT(m) \do \{ \perror(m); \exit(EXIT_FAILURE); \}while(0)void handler(int sig)
{printf("recv asig &#61; %d\n",sig);exit(EXIT_SUCCESS);
}
int main()
{int listenfd;if((listenfd &#61; socket(PF_INET,SOCK_STREAM,IPPROTO_TCP)) <0){ERR_EXIT("socket");}struct sockaddr_in servaddr;memset(&servaddr,0,sizeof(servaddr));servaddr.sin_family &#61; AF_INET;servaddr.sin_port &#61; htons(5188);servaddr.sin_addr.s_addr &#61; htonl(INADDR_ANY);int on &#61; 1;if(setsockopt(listenfd,SOL_SOCKET,SO_REUSEADDR,&on,sizeof(on)) <0){ERR_EXIT("setsockopt");}if(bind(listenfd,(struct sockaddr*)&servaddr,sizeof(servaddr)) <0){ERR_EXIT("bind");}if(listen(listenfd,SOMAXCONN) <0){ERR_EXIT("listen");}int conn;struct sockaddr_in peeraddr;socklen_t peerlen &#61; sizeof(peeraddr);if((conn &#61; accept(listenfd,(struct sockaddr*)&peeraddr,&peerlen)) <0){ERR_EXIT("accept");}printf("ip &#61; %s port &#61; %d\n",inet_ntoa(peeraddr.sin_addr),ntohs(peeraddr.sin_port));pid_t pid;pid &#61; fork();if(pid &#61;&#61; 0){signal(SIGUSR1,handler);char sendbuf[1024] &#61;{0};while(fgets(sendbuf,sizeof(sendbuf),stdin) !&#61; NULL){write(conn,sendbuf,strlen(sendbuf));memset(sendbuf,0,sizeof(sendbuf));}printf("child close\n");exit(EXIT_SUCCESS);} else {char recvbuf[1024];while(1){memset(recvbuf,0,sizeof(recvbuf));int ret &#61; read(conn,recvbuf,sizeof(recvbuf));if(ret &#61;&#61; -1){ERR_EXIT("read");}else if(ret &#61;&#61; 0){printf("peer close\n");break;}fputs(recvbuf,stdout); }printf("parent colse\n");kill(pid,SIGUSR1);exit(EXIT_SUCCESS);}return 0;}

客户端代码&#xff1a;

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define ERR_EXIT(m) \do \{ \perror(m); \exit(EXIT_FAILURE); \}while(0)
void handler(int sig)
{printf("recv a sig &#61; %d\n",sig);exit(EXIT_SUCCESS);
}
int main()
{int sock;if((sock &#61; socket(PF_INET,SOCK_STREAM,IPPROTO_TCP)) <0){ERR_EXIT("socket");}struct sockaddr_in servaddr;memset(&servaddr,0,sizeof(servaddr));servaddr.sin_family &#61; AF_INET;servaddr.sin_port &#61; htons( 5188);servaddr.sin_addr.s_addr &#61; inet_addr("127.0.0.1");if(connect(sock,(struct sockaddr*)&servaddr,sizeof(servaddr)) <0){ERR_EXIT("connect");}pid_t pid;pid &#61; fork();if(pid &#61;&#61; -1){ERR_EXIT("fork");}if(pid &#61;&#61; 0){ char recvbuf[1024] &#61; {0};while(1){memset(recvbuf,0,sizeof(recvbuf));int ret &#61; read(sock,recvbuf,sizeof(recvbuf));if(ret &#61;&#61; -1){ERR_EXIT("read");}else if(ret &#61;&#61; 0){printf("peer close \n");break;}fputs(recvbuf,stdout);}close(sock);kill(getppid(),SIGUSR1);}else {signal(SIGUSR1,handler);char sendbuf[1024] &#61; {0}; while(fgets(sendbuf,sizeof(sendbuf),stdin) !&#61; NULL){write(sock,sendbuf,strlen(sendbuf)); memset(sendbuf,0,sizeof(sendbuf)); }close(sock);}return 0;
}

执行结果

 


推荐阅读
  • 为什么即使Linux服务器的socket关闭,客户端仍能调用一次send函数?
    要弄清这个问题,首先需要知道调用send()发送数据时,发生了什么。当调用send()发送数据时,并不是直接将数据发送到网络中,而是先将待发送的数据放到socket发送缓冲区中,然 ... [详细]
  • 开发笔记:城市建设
    本文由编程笔记#小编为大家整理,主要介绍了城市建设相关的知识,希望对你有一定的参考价值。本文涉及:cdq分治、MST一道十分精妙的cdq分 ... [详细]
  • 计算机存储系统的层次结构及其优势
    本文介绍了计算机存储系统的层次结构,包括高速缓存、主存储器和辅助存储器三个层次。通过分层存储数据可以提高程序的执行效率。计算机存储系统的层次结构将各种不同存储容量、存取速度和价格的存储器有机组合成整体,形成可寻址存储空间比主存储器空间大得多的存储整体。由于辅助存储器容量大、价格低,使得整体存储系统的平均价格降低。同时,高速缓存的存取速度可以和CPU的工作速度相匹配,进一步提高程序执行效率。 ... [详细]
  • 题面传送门Solution看到什么最大值最小肯定二分啊。check直接跑一个二分图匹配就好了。orzztl!!!代码实现*mail:mle ... [详细]
  •   并查集是一种群众喜闻乐见的数据结构,其复杂度是数据结构中最奇葩的之一了,Tarjan证明其为阿克曼函数的反函数,在可以想象(不全面的解释啊)的范围内小于等于3。。。我们就把它当做O(1)吧。下面通 ... [详细]
  • 本文介绍了解决Netty拆包粘包问题的一种方法——使用特殊结束符。在通讯过程中,客户端和服务器协商定义一个特殊的分隔符号,只要没有发送分隔符号,就代表一条数据没有结束。文章还提供了服务端的示例代码。 ... [详细]
  • c语言\n不换行,c语言printf不换行
    本文目录一览:1、C语言不换行输入2、c语言的 ... [详细]
  • http:my.oschina.netleejun2005blog136820刚看到群里又有同学在说HTTP协议下的Get请求参数长度是有大小限制的,最大不能超过XX ... [详细]
  • 利用Visual Basic开发SAP接口程序初探的方法与原理
    本文介绍了利用Visual Basic开发SAP接口程序的方法与原理,以及SAP R/3系统的特点和二次开发平台ABAP的使用。通过程序接口自动读取SAP R/3的数据表或视图,在外部进行处理和利用水晶报表等工具生成符合中国人习惯的报表样式。具体介绍了RFC调用的原理和模型,并强调本文主要不讨论SAP R/3函数的开发,而是针对使用SAP的公司的非ABAP开发人员提供了初步的接口程序开发指导。 ... [详细]
  • 实现一个通讯录系统,可添加、删除、修改、查找、显示、清空、排序通讯录信息
    本文介绍了如何实现一个通讯录系统,该系统可以实现添加、删除、修改、查找、显示、清空、排序通讯录信息的功能。通过定义结构体LINK和PEOPLE来存储通讯录信息,使用相关函数来实现各项功能。详细介绍了每个功能的实现方法。 ... [详细]
  • 设计模式——模板方法模式的应用和优缺点
    本文介绍了设计模式中的模板方法模式,包括其定义、应用、优点、缺点和使用场景。模板方法模式是一种基于继承的代码复用技术,通过将复杂流程的实现步骤封装在基本方法中,并在抽象父类中定义模板方法的执行次序,子类可以覆盖某些步骤,实现相同的算法框架的不同功能。该模式在软件开发中具有广泛的应用价值。 ... [详细]
  • DescriptionclickmeSolution套路的状压期望DP题。。。考虑倒退期望:设fi,jrolepresentationstyleposi ... [详细]
  • C语言函数的定义及其含义
    本文目录一览:1、C语言函数的特点及其定义?2 ... [详细]
  • 捕获图像,用KMPlayer很容易实现。编码,用了强大的maltab生成3000多张用于播放的字符文本。图像的标号为1(1) ... [详细]
  • 一.  一就是用来乱扯的?#include<bitsstdc++.h>万能头文件#definefr(i,a,b)for(intia,_end_b;i<_en ... [详细]
author-avatar
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有