在linux平台下,用多线程实现echo服务器与客户端“一对多”(即是一台服务器可以响应多个客户端的请求)。本人写了个demo,和大家一起分享,有不足的地方,请多多指教,我是壮壮熊。

  编译时,在后面加上-lpthread。例如:g++ service2.cpp -o service2 -lpthread。否则会提示线程方面的错误。

  echo服务器端代码:

 #include<stdio.h>
#include<stdlib.h>
#include<sys/socket.h>
#include<string.h>
#include<errno.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<unistd.h>
#include<iostream>
#include<pthread.h>
using namespace std; #define SERVERIP "192.168.1.117"
#define SERVERPORT 12345
#define MAXBUFFER 256 pthread_t ntid;//线程
int connfd;//客户端连接的ID
struct sockaddr_in clientaddr; void *printContext(void *arg)
{ char ip[]={};//用来存放客户端连接的IP地址
char readBuf[MAXBUFFER]={};
int ret;
pthread_detach(ntid);//线程退出时,可以清理内存
int pconnfd=connfd;//客户端连接的ID(main函数中的accept的返回值)
//线程自己要保存连接符 ID,因为进程在第二个客户端
//连接后,会覆盖connfd
printf("%s\n",inet_ntop(AF_INET,&clientaddr.sin_addr,ip,sizeof(ip)));
cout<<"connectd to the servce"<<endl; while(ret=read(pconnfd,readBuf,MAXBUFFER))//读客户端发送的数据
{
write(pconnfd,readBuf,MAXBUFFER);//写回客户端
printf("%s\n",readBuf);//打印传输的内容
bzero(readBuf,MAXBUFFER); }
if(ret==)
{
printf("the connection of client is close!\n"); }else
{
printf("read error:%s\n",strerror(errno));
}
pthread_exit();
} int main(int argc,char** argv)
{
socklen_t len;//socket长度类型
int serverFd,ret;
struct sockaddr_in serveraddr; serverFd=socket(AF_INET,SOCK_STREAM,);//创建socket
if(serverFd<)
{
printf("socket error:%s\n",strerror(errno));
exit(-);
} bzero(&serveraddr,sizeof(serveraddr));//serveraddr清零
serveraddr.sin_family=AF_INET;
serveraddr.sin_port=htons(SERVERPORT);
inet_pton(AF_INET,SERVERIP,&serveraddr.sin_addr);//将C语言字节序转化成网络字节序 ret=bind(serverFd,(struct sockaddr *)&serveraddr,sizeof(serveraddr));
if(ret!=)
{
close(serverFd);
printf("bind error:%\n",strerror(errno));
exit(-);
} ret=listen(serverFd,);//监听
if(ret!=)
{
close(serverFd);
printf("listen error:%s\n",strerror(errno));
exit(-);
}
//clientaddr清零
len=sizeof(clientaddr);
bzero(&clientaddr,sizeof(clientaddr));
while()
{
//接收客户端的连接,然后启动线程去处理客户端发送的
//请求。线程只要保存connfd 即可。进程在第二个客户 端
//连接进来的时候,会覆盖第一个客户端的connfd
connfd=accept(serverFd,(struct sockaddr *) &clientaddr,&len);
if(connfd<)
{
printf("accept error:%s\n",strerror(errno));
continue;
} int err;
err=pthread_create(&ntid,NULL,printContext,NULL);
if(err!=)
{
cout<<"can't create pthread"<<endl;
}
//close(connfd);
}
close(serverFd);
return ;
}

  客户端代码:

 #include<stdio.h>
#include<stdlib.h>
#include<sys/socket.h>
#include<string.h>
#include<errno.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<unistd.h> #define SERVERIP "192.168.1.117"
#define SERVERPORT 12345
#define MAXBUFFER 256 int main(int argc,char** argv)
{
int clientFd,ret;
struct sockaddr_in serveraddr;
char buf[MAXBUFFER];
clientFd=socket(AF_INET,SOCK_STREAM,);//创建socket
if(clientFd<)
{
printf("socket error:%s \n",strerror(errno));
exit(-);
} bzero(&serveraddr,sizeof(serveraddr));
serveraddr.sin_family=AF_INET;
serveraddr.sin_port=htons(SERVERPORT);
inet_pton(AF_INET,SERVERIP,&serveraddr.sin_addr); //连接到服务器
ret=connect(clientFd,(struct sockaddr *)&serveraddr,sizeof(serveraddr)); if(ret!=)
{
close(clientFd);
printf("connect error:%s \n",strerror(errno));
exit(-);
}
while()
{
bzero(buf,sizeof(buf));
scanf("%s",buf);
write(clientFd,buf,sizeof(buf));//写数据
bzero(buf,sizeof(buf));
read(clientFd,buf,sizeof(buf));//读数据
printf("echo:%s\n",buf);
}
close(clientFd);
return (EXIT_SUCCESS); }

  再次提醒,编译时,在后面加上-lpthread。例如:g++ service2.cpp -o service2 -lpthread。否则会提示线程方面的错误。

  如有转载,请注明出处,谢谢!

最新文章

  1. $\LaTeX$笔记:首字下沉
  2. 【Alpha版本】 第三天 11.9
  3. java 枚举类型知识点记录
  4. 百度地图TILE算法
  5. 开发板A/D转换原理
  6. asp.net ajax 调用一例
  7. 组合逻辑的Glitch与时序逻辑的亚稳态
  8. 读写其他应用程序的SharedPreference
  9. poj 1325 Machine Schedule 最小点覆盖
  10. poj1083 贪心
  11. swift3.0基础语法(2)
  12. Dropbox + Farbox高速创建免费博客小站
  13. Java虚拟机-运行时数据区域
  14. 玩转spring mvc(六)---自定义异常跳转页面
  15. js设置回车键触发事件
  16. python 二维数组读入
  17. Python基础-列表、元祖、字典、字符串
  18. python入门(二):isinstance、内置函数、常用运算等
  19. 蓝桥杯_算法训练_区间k大数查询
  20. Java学习07 (第一遍) - Spring MVC

热门文章

  1. go开源项目influxdb-relay源码分析(一)
  2. windows phone 8.0 app 移植到windows10 app笔记
  3. [uwp]数据绑定再学习
  4. php留言系统(9)
  5. 百度地图API鼠标获取坐标
  6. 域名可以解析(ping域名可以获取正确ip),服务器本地telnet 域名+端口 无法连接,通过建立本地虚拟域名指定的方法解决该问题
  7. PHP 访问链接的3种方式
  8. vue $emit 父组件与子组件之间的通信(父组件向子组件传参)
  9. iOS --UIScrollView的学习(三)自动轮播
  10. 构造函数详解,explicit,初始化列表