跳到主要内容
极客日志极客日志面向AI+效率的开发者社区
首页博客GitHub 精选镜像工具UI配色美学隐私政策关于联系
搜索内容 / 工具 / 仓库 / 镜像...⌘K搜索
注册
博客列表
C++

Linux C++ 网络编程入门:TCP/UDP 模型与 Socket 基础

Linux C++ 网络编程涵盖字节序、IP 地址、端口号等基础概念。文章详解 Socket 接口函数如 socket、bind、listen、accept、connect、send、recv 等用法。对比 TCP 面向连接与 UDP 面向无连接的通信模型,提供 C/S 架构下的服务端与客户端代码示例,帮助开发者掌握网络通信核心流程。

CloudNative发布于 2026/3/22更新于 2026/5/2312 浏览
Linux C++ 网络编程入门:TCP/UDP 模型与 Socket 基础

文章配图

文章配图

引言:程序如何'联网'?

你有没有想过,你写的 C/C++ 程序是怎么跟千里之外的服务器交换数据的?聊天软件、网页浏览、在线游戏……这些应用程序背后都依赖着网络编程。而网络编程的核心就是 Socket(套接字)——它就像程序打开的一扇'网络窗户',数据从这扇窗户进出。

那么我们现在就从零开始,通过代码实战,彻底搞懂网络通信的核心模型。

网络编程基本概念

关于 TCP 和 UDP 的讲解我们计网篇章的传输层部分讲的内容已经足够了,本篇章的基础概念主要是围绕着字节序、IP 和端口号来展开。

一、字节序

字节序:计算机在存储多字节整数时,根据主机的 CPU 处理架构不同,我们将主机分成大端存储的主机和小端存储的主机。

  • **大端存储:**内存地址低位存储的是数据的高位
  • **小端存储:**内存地址的低位存储的是数据的低位

文章配图

我们不妨可以来验证一下我们主机是大端存储还是小端存储。

  • 使用指针来判断
#include <iostream>
int main(int argc, const char *argv[]) {
    //定义一个整形变量
    int num = 0x12345678;
    //定义一个字符类型的指针,指向整形变量的起始地址
    char *ptr = (char *)&num;
    //对 ptr 所指向的字节中的内容进行判断,如果是 0x12 则说明是大端存储
    //如果是 0x78 则说明是小端存储
    if(*ptr == 0x12){
        cout<<<<endl;
    }  (*ptr == ){
        cout << <<endl;
    }
    std::cout <<  << std::endl;
     ;
}
"big endian"
else
if
0x78
"little endian"
"Hello, World!"
return
0
  • 使用共用体来判断
#include <iostream>
#include <cstdio>
using namespace std;
//定义一个共用体类型:多个成员共享一个成员的空间,共享的是所占内存空间最大的那个成员
union Info{
    int num; //四字节整数
    char ch; //一字节
};
int main(int argc, const char *argv[]) {
    //定义一个共用体变量
    union Info temp;
    //给其整形成员赋值
    temp.num = 0x12345678;
    //判断其 ch 成员
    if(temp.ch == 0x12){
        cout<<"big endian"<<endl;
    }else if(temp.ch == 0x78){
        cout<<"little endian"<<endl;
    }
    std::cout << "Hello, World!" << std::endl;
    return 0;
}

而由于不同主机之间存储方式不同,可能会出现,小端存储的主机中的多字节整数,在网络传输过程中,明明没有出现任何问题,但是,由于大小端存储问题,导致,多字节整数传输出现错误。

基于此,我们引入的网络字节序的概念,规定网络字节序都是大端存储的。

无论发送端是大端存储还是小端存储,在传输多字节整数时,一律先转换为网络字节序。经由网络传输后,到达目的主机后,在转换为主机字节序即可。

系统给大家提供了一套有关网络字节序和主机字节序之间相互转换的函数

  • 主机:host
  • 网络:network
  • 转换:to
#include <arpa/inet.h>
//将 4 字节整数主机字节序转换为网络字节序,参数是主机字节序,返回值是网络字节序
uint32_t htonl(uint32_t hostlong);
//将 2 字节整数主机字节序转换为网络字节序,参数是主机字节序,返回值是网络字节序
uint16_t htons(uint16_t hostshort);
//将 4 字节整数的网络字节序转换为主机字节序,参数是网络字节序,返回值是主机字节序
uint32_t ntohl(uint32_t netlong);
//将 2 字节整数的网络字节序转换为主机字节序,参数是网络字节序,返回值是主机字节序
uint16_t ntohs(uint16_t netshort);

那么我们何时使用网络字节序转换函数呢?

  • 在进行多字节整数网络传输时,需要使用字节序转换函数,最典型的就是我们的端口号
  • 在进行单字节整数传输时,不需要使用
  • 在网络中传输字符串时,也不需要使用

二、IP 地址

此处在我们之前计网篇章也讲过了,但此处我们再提及下个别概念。

  • ip 地址是主机在网络中的唯一标识,由两部分组成,分别是网络号和主机号。
    • 网络号:确定计算机所从属的网络
    • 主机号:标识该设备在该网络中的一个编号

在网络传输过程中,给网络传输载体必须添加的信息,指定源 IP 地址和目的 IP 地址,以便于找到目的主机。

IP 地址的分类

IPv4:是使用 4 字节无符号整数表示的一个 ip 地址,取值范围 [0, 2^32-1] 一共有四十多亿个,很明显不够,我们采用相关技术进行扩充局域网扩充:为了解决 ip 地址不够用,让多个主机共享一个 ip 地址 WAN:wide area network (广域网)LAN:local area network(局域网)

IPv6:是使用 16 字节无符号整数表示的一个 ip 地址,取值范围【0,2^128-1】

注意:IPv6 是不兼容 IPv4 的。

文章配图

网络类型取值范围网络号个数主机号个数用途
A 类网络1.0.0.0 --- 127.255.255.2552^72^24已经保留不供给使用
B 类网络128.0.0.0 --- 191.255.255.2552^142^16名地址网管中心
C 类网络192.0.0.0 --- 223.255.255.2552^212^8家庭、校园、公司使用
D 类网络224.0.0.0 --- 239.255.255.255------组播 IP
E 类网络240.0.0.0 --- 255.255.255.255------保留、实验室使用

特殊的 IP 地址

1、网络号 + 全为 0 的主机号:表示该网络,不分配给任何主机使用,例如:192.168.10.0

2、网络号 + 全为 1 的主机号:表示当前网络的广播地址,也不分配给任何主机使用,例如:192.168.10.255

3、网络号 + 主机号为 1:默认表示网关,当然可以自己制定网关 ip

4、127.0.0.0:本地环回 ip,当没有网络时,用于测试当前主机的 ip

5、0.0.0.0:表示当前局域网中的任意一个主机号

6、255.255.255.255:一般表示广播地址


点分十进制

为了方便记忆,我们将 ip 地址的每一个字节单独计算出十进制数据,并用点进行分割,这种方式,称为点分十进制,在程序中使用的是字符串来存储的。但是,ip 地址的本质是 4 字节无符号整数,在网络中进行传输时,需要使用的是 4 字节无符号整数,而不是点分十进制的字符串。此时,就需要引入关于点分十进制数据向 4 字节无符号整数转换的相关函数。

地址:address

网络:network

转换:to

#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
//将点分十进制的 ip 地址转换为 4 字节无符号整数的网络字节序,
//参数时点分十进制数据,返回值时 4 字节无符号整数
in_addr_t inet_addr(const char *cp);
//将 4 字节无符号整数的网络字节序,转换为点分十进制的字符串
char *inet_ntoa(struct in_addr in);

三、端口号

端口号(port)是一个 2 字节的无符号整数表示的数字,取值范围【0,65535】,为了区分同一个主机之间的每个进程的,使用端口号来进行标识。

为什么不使用进程号标识,而使用端口号?

  答:因为进程号是进程的唯一标识,当同一个应用程序,关闭再打开后,并不是同一个进程号了,但是是同一个应用程序

所以,端口号标识的是我们的应用程序,当一个应用程序关闭再打开后,端口号不变。

引入端口号后,网络通信的两个重要因素就集结完毕:ip 地址:端口号,ip 地址可以在网络中,唯一确定对端的主机地址,通过端口号能够找到该主机中指定的对端应用程序。

端口号的分类

1、0~1023:众所周知的'VIP'端口号:被特殊的应用程序已经占用了的。

2、1024 ~ 49151:用户可分配的端口号

3、49152~65535:动态分配或系统自动分配的端口号


网络编程基础

一、套接字(socket)的概念

Socket 是操作系统提供的一个接口,它封装了底层网络细节。程序员通过 Socket 函数创建、绑定、连接、发送、接收数据,就像操作文件一样方便。

我们可以调用函数:socket(),创建一个用于通信的套接字端点,并返回该端点对应的文件描述符。

在通信端点中,有两个缓冲区,分别对应发送缓冲区和接收缓冲区。

文章配图

函数原型int socket(int domain, int type, int protocol);
头文件

sys/types.h

sys/socket.h

功能为通信创建一个端点,并返回该端点对应的文件描述符,文件描述符的使用原则是最小未分配 原则
参数说明

参数 1:协议族,常用的协议族如下

        AF_UNIX, AF_LOCAL     本地通信,同一主机的多进程通信

        AF_INET             提供 IPv4 的相关通信方式

        AF_INET6               提供 IPv6 的相关通信方式

具体可以看 man 7 ip

参数 2:通信类型,指定通信语义,常用的通信类型如下

        SOCK_STREAM     支持 TCP 面向连接的通信协议

        SOCK_DGRAM       支持 UDP 面向无连接的通信协议

参数 3:通信协议,当参数 2 中明确指定特定协议时,参数 3 可以设置为 0,但是有多个协议共同使用时,需要用参数 3 指定当前套接字确定的协议

返回值成功返回创建的端点对应的文件描述符,失败返回 -1 并置位错误码

二、基于 TCP 面向连接的通信方式

在网络通信过程中,有两种通信方式,分别是基于 BS 模型的,即浏览器服务器模型,和基于 CS 模型,即客户端服务器模型,本篇章,使用的是基于 CS 模型。

通信原理就是下图。

文章配图

值得一提的是,我们此处服务器用完 listen 启动监听状态,并不是我们服务器自身在等,而是相当于我们的服务器招了一位经理,这位经理来帮我们处理发来的连接请求,且这位经理还有着队列结构,当有人发来连接后,我们的经理就会看此时服务器有没有人在连接中,如果有就将其放在队列中,直到服务器的对端关闭了后再进行接受连接。

造成这一点的主要原因是上面的示例是单线程阻塞模型,同一时间只能服务一个客户端(此处的 TCP 示例中无法同时处理多个新连接,需要配合多进程/多线程/IO 多路复用)。

你可以把这一套操作想象成电话机:

  • 创建 Socket = 买一部电话机
  • Bind = 给电话机分配一个号码(端口)
  • Listen/Accept = 等待别人打进来
  • Connect = 主动拨打别人的号码
  • Send/Recv = 通话内容
📖 bind 函数
函数原型int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
头文件

sys/types.h

sys/socket.h

功能为套接字分配名称,给套接字绑定 ip 地址和端口号
参数说明

参数 1:要被绑定的套接字文件描述符

参数 2:通用地址信息结构体,对于不同的通信域而言,使用的实际结构体是不同的,该结构体的目 的是为了强制类型转换,防止警告

        通信域为:AF_INET 而言,ipv4 的通信方式

             struct sockaddr_in {

              sa_family_t    sin_family; /* 地址族:AF_INET */      

              in_port_t      sin_port;   /* 端口号的网络字节序 */

              struct in_addr sin_addr;   /* 网络地址 */

        };

        /* Internet address. */

        struct in_addr {

              uint32_t       s_addr;     /* ip 地址的网络字节序 */

        };

        通信域为:AF_UNIX 而言,本地通信

        struct sockaddr_un {

              sa_family_t sun_family;               /* 通信域:AF_UNIX */

              char        sun_path[UNIX_PATH_MAX];    /* 通信使用的文件 */

        };

参数 3:参数 2 的大小

返回值成功返回 0,失败返回 -1 并置位错误码

📖 listen 函数
函数原型int listen(int sockfd, int backlog);
头文件

sys/types.h

sys/socket.h

功能将套接字设置成被动监听状态
参数说明

参数 1:套接字文件描述符

参数 2:挂起队列能够增长的最大长度,一般为 128

返回值成功返回 0,失败返回 -1 并置位错误码

📖 accept 函数
函数原型int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
头文件

sys/types.h

sys/socket.h

功能阻塞等待客户端的连接请求,如果已连接队列中有客户端,则从连接队列中拿取第一个,并创 建一个用于通信的套接字
参数说明

参数 1:服务器套接字文件描述符

参数 2:通用地址信息结构体,用于接受已连接的客户端套接字地址信息的

参数 3:接收参数 2 的大小

返回值成功发那会一个新的用于通信的套接字文件描述符,失败返回 -1 并置位错误码

📖 recv、send 数据收发
函数原型ssize_t recv(int sockfd, void *buf, size_t len, int flags);ssize_t send(int sockfd, const void *buf, size_t len, int flags);
头文件

sys/types.h

sys/socket.h

sys/types.h

sys/socket.h

功能从套接字中读取消息放入到 buf 中向套接字文件描述符中将 buf 这个容器中的内容写入
参数说明

参数 1:通信的套接字文件描述符

参数 2:要存放数据的起始地址

参数 3:读取的数据的大小

参数 4:读取标识位,是否阻塞读取

      0:表示阻塞等待

      MSG_DONTWAIT:非阻塞

参数 1:通信的套接字文件描述符

参数 2:要发送的数据的起始地址

参数 3:发送的数据的大小

参数 4:发送标识位,是否阻塞发送

      0:表示阻塞等待

      MSG_DONTWAIT:非阻塞

返回值

可以是大于 0:表示成功读取的字节个数

可以是等于 0:表示对端已经下线(针对于 TCP 通信)

失败返回 -1,并置位错误码

成功返回发送字节的个数

失败返回 -1,并置位错误码


📖 close 关闭套接字
函数原型int close(int fd);
头文件

unistd.h

功能关闭套接字文件描述符
参数说明要关闭的套接字文件描述符
返回值成功返回 0,失败返回 -1 并置位错误码

📖 connect 连接函数
函数原型int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
头文件

sys/types.h

sys/socket.h

功能将指定的套接字,连接到给定的地址上
参数说明

参数 1:要连接的套接字文件描述符

参数 2:通用地址信息结构体

参数 3:参数 2 的大小

返回值成功返回 0,失败返回 -1 并置位错误码

三、TCP 的 C/S 模型

服务端代码实现
#include<iostream>
#include<cstdio>
#include<cstring>
#include <sys/types.h>
#include <unistd.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#define SER_PORT 8888
#define SER_IP "192.168.160.129"
int main(int argc, const char *argv[]){
    // 1、创建用于连接的套接字文件描述符
    int sfd = socket(AF_INET, SOCK_STREAM, 0);
    if(sfd == -1){
        perror("socket error");
        return -1;
    }
    printf("socket success sfd = %d\n", sfd);
    // 2、绑定 ip 地址与端口号
    struct sockaddr_in sin;
    sin.sin_family = AF_INET; // 此处绑定数字都为网络字节序
    sin.sin_port = htons(SER_PORT);
    sin.sin_addr.s_addr = inet_addr(SER_IP);
    if(bind(sfd, (struct sockaddr*)&sin, sizeof(sin)) == -1){
        perror("bind error");
        return -1;
    }
    printf("bind success\n");
    // 3、启动监听
    if(listen(sfd, 128) == -1){
        perror("listen error");
        return -1;
    }
    printf("listen success\n");
    // 4、阻塞等待客户端的连接请求
    struct sockaddr_in cin;
    socklen_t socklen = sizeof(cin);
    int newfd = accept(sfd, (struct sockaddr*)&cin, &socklen);
    if(newfd == -1){
        perror("accept error");
        return -1;
    }
    printf("[%s:%d]:已连接成功!!!\n", inet_ntoa(cin.sin_addr), ntohs(cin.sin_port));
    // 5、数据收发
    char rbuf[128] = "";
    while(1){
        bzero(rbuf, sizeof(rbuf));
        int res = recv(newfd, rbuf, sizeof(rbuf), 0);
        if(res == 0){
            printf("对端已下线\n");
            break;
        }
        printf("[%s:%d]:%s\n", inet_ntoa(cin.sin_addr), ntohs(cin.sin_port), rbuf);
        strcat(rbuf, "*_*");
        if(send(newfd, rbuf, strlen(rbuf), 0) == -1){
            perror("send error");
            return -1;
        }
        printf("send success\n");
    }
    // 6、关闭套接字
    close(newfd);
    close(sfd);
    return 0;
}
客户端代码实现
#include<iostream>
#include<cstdio>
#include<cstring>
#include <sys/types.h>
#include <unistd.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/socket.h>
using namespace std;
#define SER_PORT 8888
#define SER_IP "192.168.160.129"
#define CLI_PORT 9999
#define CLI_IP "192.168.160.129"
int main(int argc, const char *argv[]){
    // 1、创建用于通信的客户端套接字文件描述符
    int cfd = socket(AF_INET, SOCK_STREAM, 0);
    if(cfd == -1){
        perror("socket error");
        return -1;
    }
    printf("socket success cfd = %d\n", cfd);
    // 3 // 2、绑定 ip 与端口号 (可选)
    struct sockaddr_in cin;
    cin.sin_family = AF_INET;
    cin.sin_port = htons(CLI_PORT);
    cin.sin_addr.s_addr = inet_addr(CLI_IP);
    if(bind(cfd, (struct sockaddr*)&cin, sizeof(cin)) == -1){
        perror("bind error");
        return -1;
    }
    printf("绑定成功\n");
    // 3、链接服务器
    struct sockaddr_in sin;
    sin.sin_family = AF_INET;
    sin.sin_port = htons(SER_PORT);
    sin.sin_addr.s_addr = inet_addr(SER_IP);
    if(connect(cfd, (struct sockaddr*)&sin, sizeof(sin)) == -1){
        perror("connect error");
        return -1;
    }
    printf("连接服务器成功\n");
    // 4、数据收发
    char wbuf[128] = "";
    while(1){
        bzero(wbuf, sizeof(wbuf));
        fgets(wbuf, sizeof(wbuf), stdin);
        wbuf[strlen(wbuf) - 1] = 0; // 将换行改掉
        if(send(cfd, wbuf, sizeof(wbuf), 0) == -1){
            perror("send error");
            return -1;
        }
        if(recv(cfd, wbuf, sizeof(wbuf), 0) == 0){
            printf("对端已下线\n");
            break;
        }
        printf("收到服务器消息为:%s\n",wbuf);
    }
    // 5、关闭套接字
    close(cfd);
    return 0;
}

四、基于 UDP 面向无连接的通信方式

udp 通信是面向无连接的,不可靠的,尽最大努力传输的通信方式,传输过程中,可能会出现数据的丢失、重复、失序、乱序等现象创建通信套接字是,使用的传输层名称为:SOCK_DGRAM

文章配图

此处不难发现我们两种模型的函数其实也就只有数据的收发不一样。

📖 recvfrom、sendto 数据收发
函数原型ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,struct sockaddr *src_addr, socklen_t *addrlen);ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,const struct sockaddr *dest_addr, socklen_t addrlen);
头文件

sys/types.h

sys/socket.h

sys/types.h

sys/socket.h

功能从套接字中读取消息放入到 buf 中,并接受对端的地址信息结构体向套接字中发送消息,并且指定对方的地址信息结构体
参数说明

参数 1:套接字文件描述符

参数 2:存放数据的容器起始地址

参数 3:读取的数据大小

参数 4:是否阻塞

        0 表示阻塞

        MSG_DONTWAIT 表示非阻塞

参数 5:接收对端地址信息结构体的容器

参数 6:参数 5 的大小

参数 1:套接字文件描述符

参数 2:要发送的数据的起始地址

参数 3:要发送的数据大小

参数 4:是否阻塞

        0 表示阻塞

        MSG_DONTWAIT 表示非阻塞

参数 5:要发送的对端地址信息结构体

参数 6:参数 5 的大小

返回值成功返回读取字节的个数,失败返回 -1 并置位错误码成功返回发送的字节的个数,失败返回 -1 并置位错误码

五、UDP 的 C/S 模型

服务端代码实现
#include<iostream>
#include<cstdio>
#include<cstring>
#include <sys/types.h>
#include <unistd.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/socket.h>
using namespace std;
#define SER_PORT 8888
#define SER_IP "192.168.160.129"
int main(int argc, const char *argv[]){
    // 1、创建用于连接的套接字文件描述符
    int sfd = socket(AF_INET, SOCK_DGRAM, 0);
    if(sfd == -1){
        perror("socket error");
        return -1;
    }
    printf("socket success sfd = %d\n", sfd);
    // 2、绑定 ip 地址与端口号
    struct sockaddr_in sin;
    sin.sin_family = AF_INET; // 此处绑定数字都为网络字节序
    sin.sin_port = htons(SER_PORT);
    sin.sin_addr.s_addr = inet_addr(SER_IP);
    if(bind(sfd, (struct sockaddr*)&sin, sizeof(sin)) == -1){
        perror("bind error");
        return -1;
    }
    printf("bind success\n");
    // 3、数据收发
    struct sockaddr_in cin;
    socklen_t socklen = sizeof(cin);
    char rbuf[128] = "";
    while(1){
        bzero(rbuf, sizeof(rbuf));
        if(recvfrom(sfd, rbuf, sizeof(rbuf), 0, (struct sockaddr*)&cin, &socklen) == -1){
            perror("recvfrom error");
            break;
        }
        printf("[%s:%d]:%s\n", inet_ntoa(cin.sin_addr), ntohs(cin.sin_port), rbuf);
        strcat(rbuf, "*_*");
        sendto(sfd, rbuf, strlen(rbuf), 0, (struct sockaddr*)&cin, sizeof(cin));
        printf("send success\n");
    }
    // 4、关闭套接字
    close(sfd);
    return 0;
}
客户端代码实现
#include<iostream>
#include<cstdio>
#include<cstring>
#include <sys/types.h>
#include <unistd.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/socket.h>
using namespace std;
#define SER_PORT 8888
#define SER_IP "192.168.160.129"
#define CLI_PORT 9999
#define CLI_IP "192.168.160.129"
int main(int argc, const char *argv[]){
    // 1、创建用于连接的套接字文件描述符
    int cfd = socket(AF_INET, SOCK_DGRAM, 0);
    if(cfd == -1){
        perror("socket error");
        return -1;
    }
    printf("socket success sfd = %d\n", cfd);
    // 2、绑定 ip 地址与端口号
    struct sockaddr_in cin;
    cin.sin_family = AF_INET;
    cin.sin_port = htons(CLI_PORT);
    cin.sin_addr.s_addr = inet_addr(CLI_IP);
    if(bind(cfd, (struct sockaddr*)&cin, sizeof(cin)) == -1){
        perror("bind error");
        return -1;
    }
    printf("绑定成功\n");
    // 3、数据收发
    struct sockaddr_in sin;
    sin.sin_family = AF_INET;
    sin.sin_port = htons(SER_PORT);
    sin.sin_addr.s_addr = inet_addr(SER_IP);
    char wbuf[128] = "";
    while(1){
        bzero(wbuf, sizeof(wbuf));
        fgets(wbuf, sizeof(wbuf), stdin);
        wbuf[strlen(wbuf) - 1] = 0; // 将换行改成换行
        sendto(cfd, wbuf, strlen(wbuf), 0, (struct sockaddr*)&sin, sizeof(sin));
        printf("send success\n");
        recvfrom(cfd, wbuf, sizeof(wbuf), 0, NULL, NULL);
        printf("服务器发来的消息为:%s\n", wbuf);
    }
    // 4、关闭套接字
    close(cfd);
    return 0;
}

结语

网络编程其实并不神秘,核心就是:创建 Socket -> 绑定/连接 -> 收发数据 -> 关闭。

  • TCP 像打电话,建立连接后放心聊,适合重要数据。
  • UDP 像寄信,扔进邮筒就不管了,适合实时性要求高的场景。

掌握了这些基础 API,你就拿到了通往高性能服务器开发的大门钥匙,但我们目前并不能让我们的 TCP 服务器实现多台客户端的连接,那么下一步我将带着大家进入 TCP 并发服务器的学习。

目录

  1. 引言:程序如何“联网”?
  2. 网络编程基本概念
  3. 一、字节序
  4. 二、IP 地址
  5. IP 地址的分类
  6. 特殊的 IP 地址
  7. 点分十进制
  8. 三、端口号
  9. 端口号的分类
  10. 网络编程基础
  11. 一、套接字(socket)的概念
  12. 二、基于 TCP 面向连接的通信方式
  13. 📖 bind 函数
  14. 📖 listen 函数
  15. 📖 accept 函数
  16. 📖 recv、send 数据收发
  17. 📖 close 关闭套接字
  18. 📖 connect 连接函数
  19. 三、TCP 的 C/S 模型
  20. 服务端代码实现
  21. 客户端代码实现
  22. 四、基于 UDP 面向无连接的通信方式
  23. 📖 recvfrom、sendto 数据收发
  24. 五、UDP 的 C/S 模型
  25. 服务端代码实现
  26. 客户端代码实现
  27. 结语
  • 💰 8折买阿里云服务器限时8折了解详情
  • Magick API 一键接入全球大模型注册送1000万token查看
  • 🤖 一键搭建Deepseek满血版了解详情
  • 一键打造专属AI 智能体了解详情
极客日志微信公众号二维码

微信扫一扫,关注极客日志

微信公众号「极客日志V2」,在微信中扫描左侧二维码关注。展示文案:极客日志V2 zeeklog

更多推荐文章

查看全部
  • AI 绘图硬件指南:Stable Diffusion 电脑配置选择与优化
  • Ubuntu 网络环境配置实战指南
  • 新版 llama.cpp 本地部署与使用指南
  • Acconeer A121 60GHz 毫米波雷达传感器开发说明
  • LLaMA 3.1 模型部署与实战:构建智能聊天机器人
  • llama-cpp-python 从安装到 AI 应用实战指南
  • LeetCode 88:合并两个有序数组(C 语言双指针详解)
  • Linux 工程化实战:构建你的第一个命令行工具项目
  • LangChain 进阶:Vector Stores 向量存储详解
  • AI 大模型入门:文心一言与百度 AI 战略
  • Java 参数传递机制详解:值传递与引用传递的区别
  • 《AI 赋能:AI 重新定义产品经理》书籍核心内容梳理
  • Linux 文件系统核心:Ext2 Block Group 结构与 inode 索引详解
  • MCP 插件配置指南:browser-tools-mcp 示例
  • Mac 环境 GoLand 安装与配置指南
  • C++ STL list 模拟实现:双向链表与迭代器封装
  • MasterGo 设计稿转前端代码:基于 TRAE CN 与 MCP 协议实战
  • Java 微服务电商架构:Spring Cloud 多商户与 O2O 方案解析
  • Trae AI 技能创建指南:自动保存提示词功能实现
  • 论文查重与 AIGC 检测工具:Paperzz 功能解析

相关免费在线工具

  • Base64 字符串编码/解码

    将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online

  • Base64 文件转换器

    将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online

  • Markdown转HTML

    将 Markdown(GFM)转为 HTML 片段,浏览器内 marked 解析;与 HTML转Markdown 互为补充。 在线工具,Markdown转HTML在线工具,online

  • HTML转Markdown

    将 HTML 片段转为 GitHub Flavored Markdown,支持标题、列表、链接、代码块与表格等;浏览器内处理,可链接预填。 在线工具,HTML转Markdown在线工具,online

  • JSON 压缩

    通过删除不必要的空白来缩小和压缩JSON。 在线工具,JSON 压缩在线工具,online

  • JSON美化和格式化

    将JSON字符串修饰为友好的可读格式。 在线工具,JSON美化和格式化在线工具,online