• Linux网络编程--多线程实现echo服务器与客户端“一对多”功能,是网络编程的“Hello World!”


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

     

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

      echo服务器端代码

     

      1 #include<stdio.h>
      2 #include<stdlib.h>
      3 #include<sys/socket.h>
      4 #include<string.h>
      5 #include<errno.h>
      6 #include<netinet/in.h>
      7 #include<arpa/inet.h>
      8 #include<unistd.h>
      9 #include<iostream>
     10 #include<pthread.h>
     11 using namespace std;
     12 
     13 #define SERVERIP "192.168.1.117"
     14 #define SERVERPORT 12345
     15 #define MAXBUFFER 256
     16 
     17 pthread_t ntid;//线程
     18 int connfd;//客户端连接的ID
     19 struct sockaddr_in clientaddr;
     20 
     21 
     22 void *printContext(void *arg)
     23 {
     24 
     25     char ip[40]={0};//用来存放客户端连接的IP地址
     26     char readBuf[MAXBUFFER]={0};
     27     int ret;
     28     pthread_detach(ntid);//线程退出时,可以清理内存
     29     int pconnfd=connfd;//客户端连接的ID(main函数中的accept的返回值)
     30                         //线程自己要保存连接符 ID,因为进程在第二个客户端
     31                         //连接后,会覆盖connfd
     32     printf("%s
    ",inet_ntop(AF_INET,&clientaddr.sin_addr,ip,sizeof(ip)));
     33     cout<<"connectd to the servce"<<endl;
     34 
     35     while(ret=read(pconnfd,readBuf,MAXBUFFER))//读客户端发送的数据
     36     {
     37         write(pconnfd,readBuf,MAXBUFFER);//写回客户端
     38         printf("%s
    ",readBuf);//打印传输的内容
     39         bzero(readBuf,MAXBUFFER);
     40         
     41     }
     42     if(ret==0)
     43     {
     44         printf("the connection of client is close!
    ");
     45         
     46     }else
     47     {
     48         printf("read error:%s
    ",strerror(errno));
     49     }
     50     pthread_exit(0);
     51 }
     52 
     53 int main(int argc,char** argv)
     54 {
     55     socklen_t len;//socket长度类型
     56     int serverFd,ret;
     57     struct sockaddr_in serveraddr;
     58 
     59 
     60     serverFd=socket(AF_INET,SOCK_STREAM,0);//创建socket
     61     if(serverFd<0)
     62     {
     63         printf("socket error:%s
    ",strerror(errno));
     64         exit(-1);
     65     }
     66     
     67     bzero(&serveraddr,sizeof(serveraddr));//serveraddr清零
     68     serveraddr.sin_family=AF_INET;
     69     serveraddr.sin_port=htons(SERVERPORT);
     70     inet_pton(AF_INET,SERVERIP,&serveraddr.sin_addr);//将C语言字节序转化成网络字节序
     71 
     72     ret=bind(serverFd,(struct sockaddr *)&serveraddr,sizeof(serveraddr));
     73     if(ret!=0)
     74     {
     75         close(serverFd);
     76         printf("bind error:%
    ",strerror(errno));
     77         exit(-1);        
     78     }
     79     
     80     ret=listen(serverFd,5);//监听
     81     if(ret!=0)
     82     {
     83         close(serverFd);
     84         printf("listen error:%s
    ",strerror(errno));
     85         exit(-1);
     86     }
     87     //clientaddr清零
     88     len=sizeof(clientaddr);
     89     bzero(&clientaddr,sizeof(clientaddr));
     90     while(1)
     91     {
     92         //接收客户端的连接,然后启动线程去处理客户端发送的
     93         //请求。线程只要保存connfd 即可。进程在第二个客户  端
     94         //连接进来的时候,会覆盖第一个客户端的connfd
     95         connfd=accept(serverFd,(struct sockaddr *) &clientaddr,&len);
     96         if(connfd<0)
     97         {
     98             printf("accept error:%s
    ",strerror(errno));
     99             continue;
    100         }
    101         
    102         int err;
    103         err=pthread_create(&ntid,NULL,printContext,NULL);
    104         if(err!=0)
    105         {
    106             cout<<"can't create pthread"<<endl;
    107         }
    108         //close(connfd);
    109     }
    110     close(serverFd);
    111     return 0;
    112 }
    View Code

     

      客户端代码:

     1 #include<stdio.h>
     2 #include<stdlib.h>
     3 #include<sys/socket.h>
     4 #include<string.h>
     5 #include<errno.h>
     6 #include<netinet/in.h>
     7 #include<arpa/inet.h>
     8 #include<unistd.h>
     9 
    10 #define SERVERIP "192.168.1.117"
    11 #define SERVERPORT 12345
    12 #define MAXBUFFER 256
    13 
    14 int main(int argc,char** argv)
    15 {
    16     int clientFd,ret;
    17     struct sockaddr_in serveraddr;
    18     char buf[MAXBUFFER];
    19     clientFd=socket(AF_INET,SOCK_STREAM,0);//创建socket
    20     if(clientFd<0)
    21     {
    22         printf("socket error:%s 
    ",strerror(errno));
    23         exit(-1);
    24     }
    25 
    26     bzero(&serveraddr,sizeof(serveraddr));
    27     serveraddr.sin_family=AF_INET;
    28     serveraddr.sin_port=htons(SERVERPORT);
    29     inet_pton(AF_INET,SERVERIP,&serveraddr.sin_addr);
    30 
    31     //连接到服务器
    32     ret=connect(clientFd,(struct sockaddr *)&serveraddr,sizeof(serveraddr));
    33 
    34     if(ret!=0)
    35     {
    36         close(clientFd);
    37         printf("connect error:%s 
    ",strerror(errno));
    38         exit(-1);
    39     }
    40     while(1)
    41     {
    42         bzero(buf,sizeof(buf));
    43         scanf("%s",buf);
    44         write(clientFd,buf,sizeof(buf));//写数据
    45         bzero(buf,sizeof(buf));
    46         read(clientFd,buf,sizeof(buf));//读数据
    47         printf("echo:%s
    ",buf);
    48     }
    49     close(clientFd);
    50     return (EXIT_SUCCESS);
    51     
    52 }
    View Code

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

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

     

    周钦雄技术分享
  • 相关阅读:
    mysql 应用 持续更新2 转载
    sql server 用触发器记录增删改操作(转载)
    mysql 应用 持续更新
    oracle 常用指令(持续更新中....)
    转载-Oracle 数据库导入导出 dmp文件
    Web Service 服务无法连接Oracle数据库
    关于jquery获取服务器端xml数据
    Navicat Premium 自动备份mysql和sqlserver
    浅谈如何更好的打开和关闭ADO.NET连接池
    JSON 的优点
  • 原文地址:https://www.cnblogs.com/zhouqinxiong/p/3565977.html
Copyright © 2020-2023  润新知