阿里云-云小站(无限量代金券发放中)
【腾讯云】云服务器、云数据库、COS、CDN、短信等热卖云产品特惠抢购

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

125次阅读
没有评论

共计 2781 个字符,预计需要花费 7 分钟才能阅读完成。

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 ...\n");

    while(1)
    {clie_addr_len= sizeof(clie_addr);// 初始化客户端结构体长度
        cfd = accept(sfd, (struct sockaddr *)&clie_addr, &clie_addr_len);// 给客户端连接分配文件描述符, 并保存客户端 IP 端口等信息到 clie_addr 结构体中
        printf("cfd = ----------%d\n", cfd);
        printf("client IP : %s, port : %d\n", /* 打印客户端 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\n", ret);
        len = read(sfd, buf, sizeof(buf));
        printf("read len = %d\n", len);
        write(STDOUT_FILENO, buf, len);
    }

    close(sfd);// 关闭文件描述符
	return 0;
}


```

运行效果

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

如图

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

存在问题

  • 仅作学习建立 TCP 连接使用,不支持多用户,未进行错误处理。

本文永久更新链接地址:http://www.linuxidc.com/Linux/2018-01/150036.htm

正文完
星哥说事-微信公众号
post-qrcode
 0
星锅
版权声明:本站原创文章,由 星锅 于2022-01-21发表,共计2781字。
转载说明:除特殊说明外本站文章皆由CC-4.0协议发布,转载请注明出处。
【腾讯云】推广者专属福利,新客户无门槛领取总价值高达2860元代金券,每种代金券限量500张,先到先得。
阿里云-最新活动爆款每日限量供应
评论(没有评论)
验证码
【腾讯云】云服务器、云数据库、COS、CDN、短信等云产品特惠热卖中