• 回声TCP服务器端/客户端


    一、TCP服务端

    1、TCP服务端的默认函数调用顺序

    • socket()创建套接字
    • bind()分配套接字地址
    • listen()等待请求连接状态
    • accept()允许连接
    • read()/write()数据交换
    • close()断开连接

    2、进入等待连接请求状态

      只有调用了listen函数,客户端才能进入可发出连接请求的状态。即这时客户端才能调用connect()函数(若提前调用将发生错误)。

      int listen(int sock, int backlog);

      成功返回0,失败返回-1。sock指服务器端套接字,backlog指连接请求队列的长度,若为5,则队列长度为5,表示最多使5个连接请求进入队列。

    3、受理客户端连接请求

      int accept();

      accept函数受理连接请求队列中待处理的客户端连接请求。函数调用成功时,accept函数内部将产生用于数据IO的套接字,并返回其文件描述符。需要强调的是,套接字是自动创建的,并自动与发起连接请求的客户端建立连接。

    二、TCP客户端

    1、TCP客户端的默认函数调用顺序

    • socket()创建套接字
    • connect()请求连接
    • read/write数据交换
    • close()断开连接

    2、connect()

      客户端调用connect函数后,发生以下情况之一才会返回(完成函数调用):

    • 服务器端接收连接请求。
    • 发生断网等异常情况而中断连接请求。

      所谓的“接收连接”并不一位置服务器端调用accept函数,其实是服务器端把连接请求信息记录到等待队列。因此,connect函数返回后并不立即进行数据交换。

      客户端的IP地址和端口是在调用connect函数时自动分配的

    三、回声服务端/客户端

    1、linux

    服务端:

     1 #include <stdio.h>
     2 #include <stdlib.h>
     3 #include <string.h>
     4 #include <unistd.h>
     5 #include <arpa/inet.h>
     6 #include <sys/socket.h>
     7 
     8 #define BUF_SIZE 1024
     9 void error_handling(char * messages);
    10 
    11 int main(int argc, char *argv[])
    12 {
    13     if(argc != 2)
    14     {
    15         printf("Usage : %s <port>
    ", argv[0]);
    16         exit(1);
    17     }
    18     int serverSock, clientSock;
    19     struct sockaddr_in serverAddr, clientAddr;
    20     socklen_t clientAddrSize;
    21 
    22     char message[BUF_SIZE];
    23     int strLen;
    24 
    25     serverSock =socket(PF_INET, SOCK_STREAM, 0);
    26     if(serverSock == -1)
    27         error_handling("socket() error");
    28 
    29     memset(&serverAddr, 0, sizeof(serverAddr));
    30     serverAddr.sin_family = AF_INET;
    31     serverAddr.sin_addr.s_addr = htonl(INADDR_ANY);
    32     serverAddr.sin_port = htons(atoi(argv[1]));
    33 
    34     if(bind(serverSock, (struct sockaddr*) &serverAddr, sizeof(serverAddr)) == -1)
    35         error_handling("bind() error");
    36     if(listen(serverSock, 5) == -1)
    37         error_handling("listen() error");
    38 
    39     puts("Server start...");
    40     clientAddrSize = sizeof(clientAddr);
    41     for(int i = 0; i < 5; i++){
    42         clientSock = accept(serverSock, (struct sockaddr*) &clientAddr, &clientAddrSize);
    43         if(clientSock == -1)
    44             error_handling("accept() error");
    45         else
    46             printf("Connected client %d
    ", i+1);
    47         while((strLen=read(clientSock, message, BUF_SIZE)) != 0){
    48             puts("echo");
    49             write(clientSock, message, strLen);
    50         }
    51         printf("Close client %d
    ", i+1);
    52         close(clientSock);
    53     }
    54 
    55     close(serverSock);
    56     puts("Server close...");
    57     return 0;
    58 }
    59 
    60 void error_handling(char * messages)
    61 {
    62     puts(messages);
    63     exit(1);
    64 }
    View Code

    客户端:

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <unistd.h>
    #include <arpa/inet.h>
    #include <sys/socket.h>
    
    #define BUF_SIZE 1024
    void error_handling(char * messages);
    
    int main(int argc, char *argv[])
    {
        if(argc != 3)
        {
            printf("Usage : %s <IP> <port>
    ", argv[0]);
            exit(1);
        }
        int sock;
        struct sockaddr_in serv_addr;
        char message[BUF_SIZE];
        int strLen;
    
        sock = socket(PF_INET, SOCK_STREAM, 0);
        if(sock == -1)
            error_handling("socket() error");
    
        memset(&serv_addr, 0, sizeof(serv_addr));
        serv_addr.sin_family = AF_INET;
        serv_addr.sin_addr.s_addr = inet_addr(argv[1]);
        serv_addr.sin_port = htons(atoi(argv[2]));
    
        if(connect(sock, (struct sockaddr*) &serv_addr, sizeof(serv_addr)) == -1)
            error_handling("connect() error");
        else
            puts("Connected...");
        while(1){
            puts("Input message(Q to quit):");
            fgets(message, BUF_SIZE, stdin);
            if(!strcmp(message, "q
    ") || !strcmp(message, "Q
    "))
                break;
    
            strLen=strlen(message);
            write(sock, message, strlen(message));
            int recvLen = 0;
            while(recvLen < strLen){
                int recvCnt = read(sock, &message[recvLen], BUF_SIZE-1);
                if(recvCnt == -1)
                    error_handling("read() error");
                recvLen+=recvCnt;
            }
            message[recvLen]=0;
            printf("Message from server: %s
    ", message);
        }
        close(sock);
        return 0;
    }
    
    void error_handling(char * messages)
    {
        puts(messages);
        exit(1);
    }
    View Code

    2、windows

    服务端:

     1 #include <stdio.h>
     2 #include <stdlib.h>
     3 #include <WinSock2.h>
     4 
     5 #define BUF_SIZE 1024
     6 void ErrorHandling(char *message);
     7 
     8 int main(int argc, char *argv[])
     9 {
    10     if (argc != 2) {
    11         printf("Usage : %s <port>
    ", argv[0]);
    12         exit(1);
    13     }
    14 
    15     WSADATA wsaData;
    16     SOCKET serverSock, clientSock;
    17     SOCKADDR_IN serverAddr, clientAddr;
    18     int szClientAddr;
    19     char message[BUF_SIZE];
    20     int slen;
    21 
    22     if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
    23         ErrorHandling("WSAStartup() error");
    24 
    25     serverSock = socket(PF_INET, SOCK_STREAM, 0);
    26     if (serverSock == INVALID_SOCKET)
    27         ErrorHandling("socket() error");
    28     memset(&serverAddr, 0, sizeof(serverAddr));
    29     serverAddr.sin_family = AF_INET;
    30     serverAddr.sin_addr.s_addr = htonl(INADDR_ANY);
    31     serverAddr.sin_port = htons(atoi(argv[1]));
    32 
    33     if (bind(serverSock, (SOCKADDR*)&serverAddr, sizeof(serverAddr)) == SOCKET_ERROR)
    34         ErrorHandling("bind() error");
    35 
    36     if (listen(serverSock, 5) == SOCKET_ERROR)
    37         ErrorHandling("listen() error");
    38     for (int i = 0; i < 5; ++i) {
    39         szClientAddr = sizeof(clientAddr);
    40         clientSock = accept(serverSock, (SOCKADDR*)&clientAddr, &szClientAddr);
    41         if (clientSock == INVALID_SOCKET)
    42             ErrorHandling("accept() error");
    43         else
    44             printf("Connected client %d
    ", i);
    45         while ((slen =recv(clientSock, message, BUF_SIZE, 0)) != 0)
    46         {
    47             send(clientSock, message, slen, 0);
    48         }
    49         closesocket(clientSock);
    50         printf("Closed client %d
    ", i);
    51     }
    52     closesocket(serverSock);
    53     WSACleanup();
    54     return 0;
    55 }
    56 
    57 void ErrorHandling(char *message) {
    58     fputs(message, stderr);
    59     fputc('
    ', stderr);
    60 }
    View Code

    客户端:

     1 #pragma warning(disable:4996)
     2 #include <stdio.h>
     3 #include <stdlib.h>
     4 #include <string.h>
     5 #include <winsock2.h>
     6 
     7 #define BUF_SIZE 1024
     8 void ErrorHandling(char *message);
     9 
    10 int main(int argc, char* argv[]) {
    11     if (argc != 3) {
    12         printf("Usage : %s <IP> <port>
    ", argv[0]);
    13         exit(1);
    14     }
    15 
    16     WSADATA wsaData;
    17     SOCKET sock;
    18     SOCKADDR_IN serverAddr;
    19     char message[BUF_SIZE];
    20     int sLen, recvLen;
    21 
    22     if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
    23         ErrorHandling("WSAStartup() error");
    24 
    25     sock = socket(PF_INET, SOCK_STREAM, 0);
    26     if (sock == INVALID_SOCKET)
    27         ErrorHandling("socket() error");
    28 
    29     memset(&serverAddr, 0, sizeof(serverAddr));
    30     serverAddr.sin_family = AF_INET;
    31     serverAddr.sin_addr.s_addr = inet_addr(argv[1]);
    32     serverAddr.sin_port = htons(atoi(argv[2]));
    33 
    34     if (connect(sock, (SOCKADDR*)&serverAddr, sizeof(serverAddr)) == SOCKET_ERROR)
    35         ErrorHandling("connect() error");
    36     else
    37         printf("Connected.......
    ");
    38     while (1)
    39     {
    40         fputs("Input message(Q to quit):", stdout);
    41         fgets(message, BUF_SIZE, stdin);
    42         if(!strcmp(message, "q
    ") || !strcmp(message, "Q
    "))
    43             break;
    44         sLen = send(sock, message, strlen(message), 0);
    45         recvLen = 0;
    46         while (recvLen < sLen) {
    47             int cnt = recv(sock, message, BUF_SIZE - 1, 0);
    48             if (cnt == -1)
    49                 ErrorHandling("ercv() error");
    50             recvLen += cnt;
    51         }
    52         message[recvLen] = 0;
    53         printf("Message from server: %s
    ", message);
    54     }
    55     closesocket(sock);
    56     WSACleanup();
    57     return 0;
    58 }
    59 
    60 void ErrorHandling(char *message) {
    61     fputs(message, stderr);
    62     fputc('
    ', stderr);
    63 }
    View Code
  • 相关阅读:
    千亿美元规模,云计算的下半场将走向何方?
    巧用云原生能力和工具,提升云上运维效率
    基础设施代码化(IaC)的自动化配置与编排
    盘点2020 | 阿里云弹性计算年度关键词:快、弹、稳
    整体算力提升40% 芯片级安全防护 | 阿里云发布第七代ECS云服务器
    真正云原生的智能运维体系,阿里云发布ECS自动化运维套件
    安装wireshark
    查看linux的登录日志 centos7
    CentOS查看系统当前登录用户信息的4种方法
    free -m查询内存使用情况,祥解
  • 原文地址:https://www.cnblogs.com/ACGame/p/9906647.html
Copyright © 2020-2023  润新知