zoukankan      html  css  js  c++  java
  • c++ tcp 服务器和客户端例子

    目标:
      完成一个精简TCP服务器,可接收来自多个用户的请求,并返回结果。


    思路:
      (1)服务器
          C++ TCP服务器的实现主要由以下几个函数来完成:
            a)socket
         创建服务器监听套接字
      b)bind
         绑定服务器监听信息到套接字上
      c)listen
         开始监听,接收客户端的TCP连接
      d)accept
         从listen所维护的队列中取出一条已连接的TCP,返回该连接的socket描述字
            e)服务器客户端在连接socket描述字上进行消息通信
      f) close
         关闭打开着的套接字
          为了更好的服务多个发起请求的客户端,在e步骤上,我们使用fork以派生子进程来独立处理每个客户端的请求。
          if( (childpid=fork())==0)
         {
          close(listenfd);         //从父进程复制下来的监听socket描述符要关闭。
          //communication(connfd);
          exit(0);
         }
    (2)客户端
        客户端的实现主要由以下函数完成:
         a)socket
            创建客户端连接套接字
        b)connect
        向指定服务器发起连接请求
         c)服务器客户端在连接socket描述字上进行消息通信
         d)close
            关闭打开着的套接字


    实现:

    复制代码
     1 #include<sys/types.h>
    2 #include<sys/socket.h>
    3 #include<strings.h>
    4 #include<arpa/inet.h>
    5 #include<unistd.h>
    6 #include<stdlib.h>
    7 #include<stdio.h>
    8 #include<string.h>
    9 #include<errno.h>
    10 #include<signal.h>
    11 #include<sys/wait.h>
    12
    13 #define LISTEN_PORT 84
    14 void str_echo(int sockfd)
    15 {
    16 ssize_t n;
    17 char line[512];
    18
    19 printf("ready to read ");
    20 while( (n=read(sockfd,line,512))>0 )
    21 {
    22 line[n]='';
    23 printf("Client: %s ",line);
    24 bzero(&line,sizeof(line));
    25 }
    26 printf("end read ");
    27 }
    28
    29 int main(int argc, char **argv)
    30 {
    31 int listenfd, connfd;
    32 pid_t childpid;
    33 socklen_t chilen;
    34
    35 struct sockaddr_in chiaddr,servaddr;
    36
    37 listenfd=socket(AF_INET,SOCK_STREAM,0);
    38 if(listenfd==-1)
    39 {
    40 printf("socket established error: %s ",(char*)strerror(errno)); return -1;
    41 }
    42
    43 bzero(&servaddr,sizeof(servaddr));
    44 servaddr.sin_family=AF_INET;
    45 servaddr.sin_addr.s_addr=htonl(INADDR_ANY);
    46 servaddr.sin_port=htons(LISTEN_PORT);
    47
    48 int bindc=bind(listenfd,(struct sockaddr *)&servaddr,sizeof(servaddr));
    49 if(bindc==-1)
    50 {
    51 printf("bind error: %s ",strerror(errno)); return -1;
    52 }
    53
    54 listen(listenfd,5);
    55 for(;;)
    56 {
    57 chilen=sizeof(chiaddr);
    58
    59 connfd=accept(listenfd,(struct sockaddr*)&chiaddr,&chilen);
    60 if(connfd==-1)
    61 { printf("accept client error: %s ",strerror(errno)); return -1; }
    62 else
    63 printf("client connected ");
    64
    65 if((childpid=fork())==0)
    66 {
    67 close(listenfd);
    68 printf("client from %s ",inet_ntoa(chiaddr.sin_addr));
    69 str_echo(connfd);
    70 exit(0);
    71 }
    72 else if (childpid<0)
    73 printf("fork error: %s ",strerror(errno));
    74 close(connfd);
    75 }
    76 }
    复制代码

    复制代码
     1 #include<sys/types.h>
    2 #include<stdlib.h>
    3 #include<stdio.h>
    4 #include<unistd.h>
    5 #include<sys/socket.h>
    6 #include<strings.h>
    7 #include<string.h>
    8 #include<arpa/inet.h>
    9 #include<errno.h>
    10
    11 #define SERVER_PORT 84
    12 void str_cli(char *data,int sockfd)
    13 {
    14 char recv[512];
    15
    16 int wc=write(sockfd,data,strlen(data));
    17
    18 exit(0);
    19 }
    20 int main(int argc, char **argv)
    21 {
    22 int sockfd;
    23 struct sockaddr_in servaddr;
    24
    25 if(argc!=3)
    26 return -1;
    27
    28 sockfd=socket(AF_INET,SOCK_STREAM,0);
    29 if(sockfd==-1)
    30 {
    31 printf("socket established error: %s ",(char*)strerror(errno)); return -1;
    32 }
    33
    34 bzero(&servaddr,sizeof(servaddr));
    35 servaddr.sin_family=AF_INET;
    36 servaddr.sin_port=htons(SERVER_PORT);
    37 inet_pton(AF_INET,argv[1],&servaddr.sin_addr);
    38
    39 printf("client try to connect ");
    40 int conRes=connect(sockfd,(struct sockaddr *)&servaddr,sizeof(servaddr));
    41 if(conRes==-1)
    42 {
    43 printf("connect error: %s ",strerror(errno)); return -1;
    44 }
    45
    46 str_cli(argv[2],sockfd);
    47
    48 exit(0);
    49 }
    复制代码

    分析:
       最简单的服务器仅能完成基本的通信,并没有考虑其他边界或者异常情况,同时,采用子进程处理客户端连接,一旦子进程数量增多,并且子进程需要长时间的运行,那么服务器性能将严重下降。

  • 相关阅读:
    LeetCode100-相同的树
    LeetCode66-加一
    LeetCode102-二叉树的层序遍历
    dubbo协议端口
    http错误-413 Request Entity Too Large
    【Jeecg Vue】通过getAction的finally来最大程度避免影响主数据呈现
    图片压缩,用这个就够了
    信息数据安全,日常办公你就要注意这些!
    java笔记:流式编程 数组与List集合互转
    改状态,你会改吗?你真的会改吗?
  • 原文地址:https://www.cnblogs.com/daochong/p/6873315.html
Copyright © 2011-2022 走看看