TCP编程流程

一、TCP 服务器的网络编程流程

TCP 服务器的网络编程流程 (搭配客户端流程),核心是用socket相关函数实现 "服务器监听→客户端连接→收发数据" 的逻辑。我用 "开奶茶店" 的类比来讲解,同时给代码加通俗注释:

服务器流程 :像 "开奶茶店"------ 先准备店铺(socket)→挂招牌(bind绑定 IP + 端口)→开门等客(listen监听)→接待顾客(accept建立连接)→接单 / 出餐(recv收数据 /send发数据)→关门(close)。

cpp 复制代码
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

int main()
{
    // 1. 创建套接字:相当于"开奶茶店前,先租个店面(申请网络通信的'通道')"
    // AF_INET=用IPv4,SOCK_STREAM=用TCP协议,0=默认协议
    int sockfd = socket(AF_INET, SOCK_STREAM, 0); //tcp 创建套接字
    if (sockfd == -1)  // 如果开店失败(比如没权限)
    {
        exit(1);  // 直接关门不干了
    }

    // 2. 准备"店铺地址信息":相当于"写清楚奶茶店的地址(IP)和门牌号(端口)"
    struct sockaddr_in saddr,caddr;  // 存地址的结构体
    memset(&saddr,0,sizeof(saddr));  // 先清空地址信息
    saddr.sin_family = AF_INET;      // 用IPv4地址
    saddr.sin_port = htons(6000);    // 门牌号(端口):6000,htons是转成网络字节序
    saddr.sin_addr.s_addr = inet_addr("127.0.0.1"); // 店铺地址(IP):本地回环地址(自己电脑)

    // 3. 绑定地址:相当于"把地址挂到店门口(让别人能找到这个店)"
    // 把sockfd(店面)和saddr(地址)绑定
    int res = bind(sockfd,(struct sockaddr*)&saddr,sizeof(saddr));
    if (res == -1 )  // 如果绑定失败(比如端口被占用)
    {
        printf("bind err\n");  // 打印"地址挂不上"
        exit(1);  // 关门
    }

    // 4. 监听:相当于"开门营业,最多同时接待5个排队的顾客"
    listen(sockfd,5);  // 第二个参数是"排队长度"

    // 5. 循环接待顾客:一直开着店等客人
    while( 1 )
    {
        int len = sizeof(caddr);  // 存"顾客地址"的长度
        // 接待顾客:相当于"从排队的人里接一个进来,建立单独的'服务通道'(c)"
        // 这里会"阻塞"------没人来就一直等
        int c = accept(sockfd,(struct sockaddr*)&caddr,&len); //可能阻塞
        if (c < 0 )  // 如果接待失败
        {
            continue;  // 不管他,等下一个顾客
        }
        printf("accept c=%d\n",c);  // 打印"接待的顾客编号(c是新的套接字)"

        // 6. 收顾客的点单:相当于"接顾客的订单"
        char buff[128] = {0};  // 存订单的缓冲区
        // recv从"顾客通道c"收数据,存在buff里,最多收127字节
        int n = recv(c,buff,127,0);
        printf("buff=%s\n",buff);  // 打印"顾客点的单(收到的数据)"

        // 7. 给顾客出餐:相当于"把奶茶给顾客"
        send(c,"ok",2,0);  // 给"顾客通道c"发"ok"(回复数据)

        // 8. 送走顾客:相当于"这个顾客服务完了,关掉单独的通道"
        close(c);
    }
}

二、客户端流程

cpp 复制代码
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

int main()
{
    // 1. 创建套接字:相当于"顾客准备好'手机'(用来联系奶茶店)"
    // AF_INET=用IPv4,SOCK_STREAM=用TCP协议(靠谱的连接)
    int sockfd = socket(AF_INET,SOCK_STREAM,0);
    if ( sockfd == -1 )  // 如果"手机"坏了(创建失败)
    {
        exit(1);  // 没法买奶茶了,走人
    }

    // 2. 准备"奶茶店的地址":相当于"查奶茶店的地址(IP)和门牌号(端口)"
    struct sockaddr_in saddr;  // 存奶茶店地址的结构体
    memset(&saddr,0,sizeof(saddr));  // 清空地址
    saddr.sin_family = AF_INET;      // 用IPv4地址
    saddr.sin_port = htons(6000);    // 奶茶店的门牌号(端口):6000
    saddr.sin_addr.s_addr = inet_addr("127.0.0.1"); // 奶茶店地址(IP):本地回环(和服务器在同一台电脑)

    // 3. 连接奶茶店:相当于"顾客走到奶茶店门口,敲门进店"
    int n = connect(sockfd,(struct sockaddr*)&saddr,sizeof(saddr));
    if ( n == -1 )  // 如果敲门没人开(连接失败,比如服务器没开)
    {
        printf("connect err\n");  // 打印"连不上奶茶店"
        exit(1);  // 走人
    }

    // 4. 点单:相当于"顾客告诉店员要喝什么"
    char buff[128] = {0};  // 存点单内容的缓冲区
    fgets(buff,128,stdin); // 从键盘输入点单内容(比如输入"一杯珍珠奶茶")
    // 把点单内容通过"手机(sockfd)"发给奶茶店
    send(sockfd,buff,strlen(buff)-1,0); // strlen(buff)-1是去掉输入的换行符

    // 5. 拿奶茶:相当于"接收店员给的奶茶"
    memset(buff,0,sizeof(saddr));  // 清空缓冲区,准备接奶茶
    recv(sockfd,buff,127,0);       // 从"手机"收服务器的回复(比如"ok")
    printf("buff=%s\n",buff);      // 打印收到的回复

    // 6. 离开:相当于"喝完奶茶,离开店铺"
    close(sockfd);  // 关掉"手机"(断开连接)
    exit(0);
}

客户端核心流程(对应 "买奶茶")

  1. socket:准备 "联系工具"(对应手机);
  2. 填地址:查 "奶茶店的 IP + 端口";
  3. connect:走到奶茶店门口(建立连接);
  4. send:告诉店员点什么(发数据);
  5. recv:拿到店员给的奶茶(收数据);
  6. close:喝完走人(断开连接)。

和服务器的对应关系

  • 客户端的connect,对应服务器的accept(一个 "敲门",一个 "开门接待");
  • 客户端的send/recv,对应服务器的recv/send(双方互相发 / 收数据)。

三、测试

相关推荐
allway21 天前
Understanding and Resolving StrictModes Issues in SSHD Configuration
运维·服务器
米高梅狮子1 天前
7. Linux RAID 存储技术
linux·运维·服务器
莳花微语1 天前
磐维数据库双中心容灾流复制集群搭建
服务器·数据库·oracle
Qianliwind1 天前
安卓手机作为服务器安装docker安装外网可访问网站
服务器·docker·容器
lbb 小魔仙1 天前
Linux 服务器安全配置:iptables + SELinux 防御策略全解析
linux·服务器·安全
Maggie_ssss_supp1 天前
Linux-LNMP生产环境部署
linux·运维·服务器
数字护盾(和中)1 天前
破局 “形式化培训”:企业网络安全意识提升的痛点与实操策略
网络
网运少年1 天前
一文了解5G切片的原理
网络·5g
2501_915918411 天前
iOS App的tcp、udp数据包抓取在实际开发中的使用方式
android·tcp/ip·ios·小程序·udp·uni-app·iphone