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(双方互相发 / 收数据)。

三、测试

相关推荐
佑白雪乐23 分钟前
<Linux基础第10集>复习前面内容
linux·运维·服务器
春日见26 分钟前
自动驾驶规划控制决策知识点扫盲
linux·运维·服务器·人工智能·机器学习·自动驾驶
landonVM2 小时前
Linux 上搭建 Web 服务器
linux·服务器·前端
学习中的DGR2 小时前
[极客大挑战 2019]Http 1 新手解题过程
网络·python·网络协议·安全·http
乐迪信息2 小时前
乐迪信息:AI防爆摄像机在船舶监控的应用
大数据·网络·人工智能·算法·无人机
云游云记2 小时前
nesbot/carbon 常用功能总结
linux·运维·服务器
landonVM2 小时前
Linux 下的高效压缩工具 Zstandard
linux·运维·服务器
遇见火星3 小时前
服务器运维操作命令速查手册
运维·服务器
天天睡大觉3 小时前
Python学习12
网络·python·学习
i建模3 小时前
如何设置宿主的windows11系统访问HyperV的虚拟机,同时该虚拟机可以上网
网络