zoukankan      html  css  js  c++  java
  • Linux单用户CS模型TCP通讯完全注释手册

    Linux单用户CS模型TCP通讯完全注释手册

    server

    描述

    • 实现一个简单的Linux单用户CS通讯,客户端发送一串字符串,服务器将其转换为大写后返回。

    server 代码

    ```
    #include <stdio.h>
    #include <unistd.h>
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <string.h>
    #include <ctype.h>
    #include <arpa/inet.h>
    #define SERV_PORT 6666
    int main(int argc,char *argv[])
    {
        int sfd, cfd;//定义服务器的文件描述符std, 定义客户端的文件描述符cfd, cfd用来与客户端通讯,sfd用来接受客户端接入请求.
        int len, i;//定义读取客户端数据长度返回值len, 定义操作字符时的循环变量i
        char buf[BUFSIZ], clie_IP[BUFSIZ];//定义buf接收字符串, 定义clie_IP接收套接字中客户端IP
        struct sockaddr_in serv_addr, clie_addr;//定义服务器结构体,客户端结构体
        socklen_t clie_addr_len;//定义客户端套接字长度
    
        sfd = socket(AF_INET, SOCK_STREAM, 0);//创建一个服务器套接字,返回文件描述符
    
        bzero(&serv_addr, sizeof(serv_addr));//给结构体清零
        serv_addr.sin_family = AF_INET;//设置结构体协议族为IPv4
        serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);//设置结构体IP为所有有效网卡的IP,这里需要用htonl将INADDR_ANY转为网络字节序.
        serv_addr.sin_port = htons(SERV_PORT);//设置端口,这里htons为转为网络字节序
    
        bind(sfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr));//设置文件描述符与结构体绑定(ip, port, 网卡等).
    
        listen(sfd, 2);//参数2为半连接及已连接但在等待accept分配文件描述符的连接数的总和,Linux默认最大128(该值可修改)
    
        printf("Wait for client connect ...
    ");
    
        while(1)
        {
            clie_addr_len= sizeof(clie_addr);//初始化客户端结构体长度
            cfd = accept(sfd, (struct sockaddr *)&clie_addr, &clie_addr_len);//给客户端连接分配文件描述符,并保存客户端IP端口等信息到clie_addr结构体中
            printf("cfd = ----------%d
    ", cfd);
            printf("client IP : %s, port : %d
    ", /*打印客户端IP,端口号,这里从in_addr_t类型转换到字符串类型,需要用inet_ntop函数*/
                   inet_ntop(AF_INET, &clie_addr.sin_addr.s_addr, clie_IP, sizeof(clie_IP)), 
                   ntohs(clie_addr.sin_port)/*将端口号转换为本地字节序*/
                  );
            do  //循环处理客户端请求
            {
                len = read(cfd, buf, sizeof(buf));
                write(STDOUT_FILENO, buf, len);
                for(i = 0; i< len; ++i)
                {
                    buf[i] = toupper(buf[i]);
                }
                write(cfd, buf, len);
            }while(len);
            close(cfd);//通讯结束,关闭客户端文件描述符
        }
        close(sfd);//通讯结束,关闭服务器文件描述符
    
        return 0;
    }
    
    ```
    

    client代码实现

    ```
    #include <stdio.h>
    #include <unistd.h>
    #include <string.h>
    #include <sys/socket.h>
    #include <arpa/inet.h>
    #define SERV_IP "127.0.0.1"
    #define SERV_PORT 6666
    
    int main(int argc,char *argv[])
    {
        int sfd, len;//定义与server通讯的文件描述符sfd, 定义读取到的数据(server发的)的长度len
        struct sockaddr_in serv_addr;//定义与server通讯的套接字serv_addr
        char buf[BUFSIZ];//定义buf接收server发送的数据
    
        sfd = socket(AF_INET, SOCK_STREAM, 0);//初始化文件描述符sfd,协议族为AF_INET(即IPv4), 应用协议为SOCK_STREAM(即TCP协议),第三个参数默认0
    
        bzero(&serv_addr, sizeof(serv_addr));//将套接字清零
    
        serv_addr.sin_family = AF_INET;//设置套接字协议族为IPv4
        inet_pton(AF_INET, SERV_IP, &serv_addr.sin_addr.s_addr);//将IP地址转换为in_addr_t类型存入
        serv_addr.sin_port = htons(SERV_PORT);//将端口转为网络字节序存入
    
        connect(sfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr));//按照套接字里服务器信息连接服务器,并设置sfd文件描述符用来通讯
    
        while(1)//与服务器通讯过程,本例为给server发送一行数据,然后打印server发回的数据.
        {
            fgets(buf, sizeof(buf), stdin);
            int ret = write(sfd, buf, strlen(buf));
            printf("write ret = %d
    ", ret);
            len = read(sfd, buf, sizeof(buf));
            printf("read len = %d
    ", len);
            write(STDOUT_FILENO, buf, len);
        }
    
        close(sfd);//关闭文件描述符
    	return 0;
    }
    
    
    ```
    

    运行效果

    • 客户端输入:hello,world
    • 服务端转换为大写后返回,客户端收到服务器发回的数据后进行打印:HELLO,WORLD

    如图

    存在问题

    • 仅作学习建立TCP连接使用,不支持多用户,未进行错误处理。
  • 相关阅读:
    Educational Codeforces Round 13
    Educational Codeforces Round 12
    vscode 修改标签栏样式为换行全部展示
    webpack uglifyjs 报错 Unexpected token name
    tsconfig.js 使用 paths 设置alias无效问题
    Webpack 报错 filename.indexOf is not a function 的问题
    'GL_EXT_shader_framebuffer_fetch' : extension is not supported
    Flutter命令突然无响应、vscode突然无法连接到IOS模拟器
    解决node fs.writeFile 生成csv 文件乱码问题
    数组map方法与如何使用ES5实现
  • 原文地址:https://www.cnblogs.com/linkyip/p/8168940.html
Copyright © 2011-2022 走看看