美文网首页
TCP收发DEMO

TCP收发DEMO

作者: 枫叶情结 | 来源:发表于2019-01-09 18:40 被阅读11次

    1、客户端

    /*socket tcp客户端*/
    #include <sys/stat.h>
    #include <fcntl.h>
    #include <errno.h>
    #include <netdb.h>
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <arpa/inet.h>
    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    #include <unistd.h>
    
    #define SERVER_PORT 6666 //端口号
    
    /*
     连接到服务器后,会不停循环,等待输入,
     输入quit后,断开与服务器的连接
     */
    int main()
    {
      //客户端只需要一个套接字文件描述符,用于和服务器通信
      int clientSocket;
      
      //声明sockaddr_in结构体变量,用于构建服务器的IP地址 端口号 地址类型
      struct sockaddr_in serverAddr;
      
      char sendbuf[200]; //发送缓冲区
      char recvbuf[200]; //接收缓冲区
      
      long iDataCount; //本次所接收到的字符串长度(如:"123",则iDataCount=3)
      
      /*
       socket函数,失败返回-1
       int socket(int domain, int type, int protocol);
       第一个参数表示使用的地址类型,AF_INET就是使用IPv4进行通信
       第二个参数表示套接字类型: SOCK_STREAM则是TCP通信  SOCK_DGRAM则是UDP通信
       第三个参数设置为0
       */
      if((clientSocket = socket(AF_INET, SOCK_STREAM, 0)) < 0)//调用 socket() 函数创建套接字
      {
        perror("socket");
        return 1;
      }
      
      serverAddr.sin_family = AF_INET;  //设置的使用地址类型
      serverAddr.sin_port = htons(SERVER_PORT); //设置端口号
      //指定服务器端的ip,本地测试:10.8.116.226
      //inet_addr()函数,将点分十进制IP转换成网络字节序IP
      serverAddr.sin_addr.s_addr = inet_addr("10.8.116.226");//设置IP地址
      
      //建立连接
      if(connect(clientSocket, (struct sockaddr *)&serverAddr, sizeof(serverAddr)) < 0)
      {
        perror("connect");
        return 1;
      }
      
      printf("连接到主机...\n");
      
      //接收发送数据
      while(1)
      {
        //1:发送数据部分
        printf("发送消息:");
        scanf("%s", sendbuf); //scanf输入函数,输入信息存在发送缓冲器里
        printf("\n");
        //发送数据
        send(clientSocket, sendbuf, strlen(sendbuf), 0);
        
        
        //2:比较两个字符串
        if(strcmp(sendbuf, "quit") == 0)
          break;
        
        
        //3:接收数据部分
        printf("读取消息:");
        recvbuf[0] = '\0';
        iDataCount = recv(clientSocket, recvbuf, 200, 0); //接收数据
        recvbuf[iDataCount] = '\0';
        printf("%s\n", recvbuf);
      }
      
      //关闭套接字,将套接字描述符(或句柄)从内存清除
      close(clientSocket);
      
      
      return 0;
    }
    

    2、服务端

    /*socket tcp服务器端*/
    #include <sys/stat.h>
    #include <fcntl.h>
    #include <errno.h>
    #include <netdb.h>
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <arpa/inet.h>
    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    #include <unistd.h>
    
    #define SERVER_PORT 6666 //端口号
    
    /*
     监听后,一直处于accept阻塞状态,
     直到有客户端连接,
     
     当客户端如quit后,断开与客户端的连接
     */
    int main()
    {
      int serverSocket;//服务器套接字的文件描述符(通过调用socket函数获得)
      int clientSocket;//客户端套接字的文件描述符(通过接收得到)
      
      //声明sockaddr_in结构体变量,分别用于构建服务器和客户端的IP地址 端口号 地址类型
      struct sockaddr_in serverAddr;
      struct sockaddr_in clientAddr;
      
      int addrLen = sizeof(clientAddr);//缓冲区的clientAddr的长度
      
      char sendbuf[200]; //发送缓冲区
      char recvbuf[200]; //接收缓冲区
      
      long iDataCount; //本次所接收到的字符串长度(如:"abc",则iDataCount=3)
      
      /*
       socket函数,失败返回-1
       int socket(int domain, int type, int protocol);
       第一个参数表示使用的地址类型,AF_INET就是使用IPv4进行通信
       第二个参数表示套接字类型: SOCK_STREAM则是TCP通信  SOCK_DGRAM则是UDP通信
       第三个参数设置为0
       */
      if((serverSocket = socket(AF_INET, SOCK_STREAM, 0)) < 0)
      {
        perror("socket");
        return 1;
      }
      
      /*
       置零函数
       server_addr:要置零的数据的起始地址
       sizeof(server_addr):要置零的数据字节个数
       */
      bzero(&serverAddr, sizeof(serverAddr));
      
      //初始化服务器端的套接字,并用htons和htonl将端口和地址转成网络字节序
      serverAddr.sin_family = AF_INET; //设置的使用地址类型
      serverAddr.sin_port = htons(SERVER_PORT); //设置端口号
    //  //ip可是是本服务器的ip,也可以用宏INADDR_ANY代替,代表0.0.0.0,表明所有地址
    //  server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
      serverAddr.sin_addr.s_addr = inet_addr("10.8.116.226");//设置IP地址
      
    
      /*
       bind将socket与本机的一个端口绑定,随后就可以在该端口监听服务请求
       对于bind,accept之类的函数,里面套接字参数都是需要强制转换成(struct sockaddr *)
       bind三个参数:服务器端的套接字的文件描述符,
       */
      if(bind(serverSocket, (struct sockaddr *)&serverAddr, sizeof(serverAddr)) < 0)
      {
        perror("connect");
        return 1;
      }
      
      //服务器端调用listen()函数后,套接字进入listen状态,开始监听客户端请求
      if(listen(serverSocket, 5) < 0)
      {
        perror("listen");
        return 1;
      }
      
      
      while(1)
      {
        printf("监听端口: %d\n", SERVER_PORT);
        
        /*
          调用accept函数后,会进入阻塞状态
         accept返回一个套接字的文件描述符,这样服务器端便有两个套接字的文件描述符
         serverSocket和clientSocket
         serverSocket仍然继续在监听状态,clientSocket则负责接收和发送数据
         clientAddr是一个传出参数,accept返回时,传出客户端的地址和端口号
         addrLen是一个传入-传出参数,传入的是调用者提供的缓冲区的clientAddr的长度,以避免缓冲区溢出
         传出的是客户端地址结构体的实际长度
         出错返回-1
         */
        clientSocket = accept(serverSocket, (struct sockaddr*)&clientAddr, (socklen_t*)&addrLen);
        
        if(clientSocket < 0)
        {
          perror("accept");
          continue;
        }
        
        
        printf("等待消息...\n");
        //inet_ntoa ip地址转换函数,将网络字节序IP转换为点分十进制IP
        printf("IP is %s\n", inet_ntoa(clientAddr.sin_addr));
        printf("Port is %d\n", htons(clientAddr.sin_port));
        
        
        while(1)
        {
          //1:接收数据部分
          printf("读取消息:");
          
          recvbuf[0] = '\0';
          iDataCount = recv(clientSocket, recvbuf, 1024, 0);
          
          if(iDataCount < 0)
          {
            perror("recv null");
            continue;
          }
          recvbuf[iDataCount] = '\0';
          printf("%s\n", recvbuf);
          
          
          //2:比较两个字符串
          if(strcmp(recvbuf, "quit") == 0)
            break;
          
          
          
          
          //3:发送数据部分
          printf("发送消息:");
          scanf("%s", sendbuf);//scanf输入函数,输入信息存在发送缓冲区里
          printf("\n");
          //发送数据
          send(clientSocket, sendbuf, strlen(sendbuf), 0);
          
          
          
          if(strcmp(sendbuf, "quit") == 0)
            break;
          
        }
      }
      
      //关闭套接字,将套接字描述符(或句柄)从内存清除
      close(serverSocket);
      
      return 0;
    }
    

    相关文章

      网友评论

          本文标题:TCP收发DEMO

          本文链接:https://www.haomeiwen.com/subject/ltogrqtx.html