Socket 编程 TCP

article/2025/9/5 9:53:00

目录

1. TCP socket API 详解

1.1 socket

1.2 bind

1.3 listen

1.4 accept

1.5 read&&write

1.6 connect

1.7 recv

1.8 send

1.9 popen

1.10 fgets

2. EchoServer

3. 多线程远程命令执行

4. 引入线程池版本翻译

5. 验证TCP - windows作为client访问Linux

6. connect的断线重连


1. TCP socket API 详解

下面介绍程序中用到的socket API,这些函数都在sys/socket.h中。

1.1 socket

// main socket
NAMEsocket - create an endpoint for communicationSYNOPSIS#include <sys/types.h>          /* See NOTES */#include <sys/socket.h>int socket(int domain, int type, int protocol);
// domain:域,表示要进行网络通信,AF_INET
// type:套接字类型,TCP就填SOCK_STREM(流式套接字),UDP就填SOCK_DGRAM(数据包套接字)
// protocol:设置为0,默认就是TCP Socket// 返回值
RETURN VALUEOn success, a file descriptor for the new socket is returned.  On error, -1 is returned, and errno is set appropriately.
// 跟UDP一样,成功就是新的文件描述符,失败就返回-1

1.2 bind

// man bind
NAMEbind - bind a name to a socketSYNOPSIS#include <sys/types.h>          /* See NOTES */#include <sys/socket.h>int bind(int sockfd, const struct sockaddr *addr,socklen_t addrlen);
// 填充当前服务器本地的socket信息,文件信息和网络信息关联起来。// 返回值
RETURN VALUEOn success, zero is returned.  On error, -1 is returned, and errno is set appropriately.
// 如果成功了0被返回,否则-1被返回

1.3 listen

TCP的有连接和UDP的无连接

UDP叫面向数据报,无连接的,TCP叫面向字节流,有连接的,怎么证明UDP是无连接的呢?

只要我客户端一启动,随时就可以向服务器发消息,所以我们直接创建套接字之后,直接sendto就可以向服务器发消息了,没有所谓的连接,而TCP叫做面向连接的协议,即有连接,所以我们对应的TCP,要面向连接,如果我们的客户端(c)连接服务器(s),也叫cs模式,如果c向s发起对应的请求,就先的建立连接,连接建立成功才能通信,这就是TCP的特点,而客户点要连服务器,是不是要求这个服务器随时随地等待被连接。所以TCP是建立连接的,一定会存在协商的过程,所以tcp需要将socket设置为监听状态。

// man listen
NAMElisten - listen for connections on a socket// 意思就是再等别人随时随地来连接我SYNOPSIS#include <sys/types.h>          /* See NOTES */#include <sys/socket.h>int listen(int sockfd, int backlog);
// sockfd:设置的文件描述符
// backlog:服务器所对应的操作系统中所对应的全连接的个数,不建议为0,也不能太长,8,4,14,32都可以,具体设置多大,按照自己的需求来做,backlog是积压的意思,就类似于排队,但是排队也不能排太长// 返回值
RETURN VALUEOn success, zero is returned.  On error, -1 is returned, and errno is set appropriately.
// 成功了返回0,失败了-1被返回

1.4 accept

// man accept
NAMEaccept, accept4 - accept a connection on a socketSYNOPSIS#include <sys/types.h>          /* See NOTES */#include <sys/socket.h>int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);#define _GNU_SOURCE             /* See feature_test_macros(7) */#include <sys/socket.h>int accept4(int sockfd, struct sockaddr *addr,socklen_t *addrlen, int flags);// 从指定的文件描述符当中获取新连接,获取新的客户端,当别人连接你的时候,第一件是就是要知道谁来连我,
// sockfd:套接字
// addr && addrlen:输出型参数,其实就相当于给我们传进来缓冲区,当我们再进行获取新连接,这个上面所对应的sockaddr的客户端的地址就会直接给我们返回。这两个参数就等同于recvfrom,recvfrom的后两个参数。// 返回值
RETURN VALUEOn success, these system calls return a nonnegative integer that is a file descriptor for the accepted socket.  On error, -1 is returned, errno is set appropriately, and addrlen is left unchanged.
// 如果成功就返回非0,失败-1返回。没有人连接就会阻塞。
// 成功后,这些系统调用将返回一个非负整数,该整数是所接受套接字的文件描述符,
// 正真提供服务的是由accept的返回值来定的。而sockfd是专门用来获取新连接的。

1.5 read&&write

读和写我们用的是read和write,因为我们的accept返回的是一个文件描述符,而且TCP是面向字节流的,管道和文件也是面向字节流的,所以TCP套接字,在我们获得了新的文件描述符之后,TCP套接字往后的处理都跟我们之前学习文件跟管道一样,我们可以调用read和write这样的文件接口来直接对网络进行读和写。

UDP不敢用read和write,因为UDP是面向数据报的,报文类型上是不一样的,至于什么是面向数据报,什么是面向字节流,单纯在应用层上编写代码是感受不到的,到TCP和UDP的原理时才能感受的到。

void HandlerRequest(int sockfd) // TCP也是全双工{char inbuffer[4096];while(true){size_t n = ::read(sockfd,inbuffer,sizeof(inbuffer)-1);if(n > 0){LOG(LogLevel::INFO) << inbuffer;inbuffer[n] = 0;std::string echo_str = "server echo# ";echo_str += inbuffer;::write(sockfd,echo_str.c_str(),echo_str.size());}}}void Start(){_isrunning = true;while(_isrunning){// 不能直接读数据// 1. 获取新连接struct sockaddr_in peer;socklen_t peerlen;int sockfd = ::accept(_listensockfd,CONV(&peer),&peerlen);if(sockfd < 0){LOG(LogLevel::WARNING) << "accept error: " << strerror(errno);continue;// 失败了不是报错,而是回头重新来}// 获取连接成功了LOG(LogLevel::INFO) << "accept success,sockfd id : " << sockfd;// version-0HandlerRequest(sockfd);}_isrunning = false;}

1.6 connect

// man connect
NAMEconnect - initiate a connection on a socketSYNOPSIS#include <sys/types.h>          /* See NOTES */#include <sys/socket.h>int connect(int sockfd, const struct sockaddr *addr,socklen_t addrlen);
// sockfd:客户端所创建的套接字
// addr && addrlen:访问目标服务器所对应的IP地址和端口号,// 返回值
RETURN VALUEIf the connection or binding succeeds, zero is returned.  On error, -1 is returned, and  errno  is  set  appropri‐ately.
// 创建套接字成功,返回值就是0,否则就是-1.

1.7 recv

// man recv
NAMErecv, recvfrom, recvmsg - receive a message from a socketSYNOPSIS#include <sys/types.h>#include <sys/socket.h>ssize_t recv(int sockfd, void *buf, size_t len, int flags);
// 从指定的文件描述符读取数据到buffer,长度是len,flage就是读取的标志位,默认设置为0就可以了,因为在我们当前的代码中,设置为0就表示的是阻塞的,他比read就多了一个flags,这是专门在套接字当中为我们处理IO接口,

1.8 send

// man send
NAMEsend, sendto, sendmsg - send a message on a socketSYNOPSIS#include <sys/types.h>#include <sys/socket.h>ssize_t send(int sockfd, const void *buf, size_t len, int flags);
// 把特定缓冲区指定长度通过该文件描述符发出去,他也多了一个flags参数。

不管是read、write、recv还是end,他们的返回值的意思都是一样的,所以可以平滑过渡。

1.9 popen

// man popen
#include <stdio.h>
NAMEpopen, pclose - pipe stream to or from a processSYNOPSIS#include <stdio.h>FILE *popen(const char *command, const char *type);int pclose(FILE *stream);
// 它的底层其实就是帮我们做了这几件事情
/*
1. 执行 Shell 命令
启动一个新的子进程,运行指定的命令行程序(如 ls, grep, python 等)。
2. 建立单向管道
根据模式(读或写),创建一个管道:
读模式("r"):从子进程的输出(如 stdout)读取数据。
写模式("w"):向子进程的输入(如 stdin)写入数据。
3. 返回文件流指针
返回一个 FILE* 指针,可通过标准文件操作函数(如 fread, fgets, fprintf)与子进程交互。
*/
// 1. pipe
// 2. fork + dup2(pipe[1],1) + exec*,执行结果给父进程,pipe[0]
// 3. return
// 返回值是FILE*的,其实就是把管道封装起来,封装成一个文件了。// 返回值
RETURN VALUEpopen(): on success, returns a pointer to an open stream that can be used to read or write to  the  pipe;  if  the fork(2) or pipe(2) calls fail, or if the function cannot allocate memory, NULL is returned.// 成功的话就返回一个文件流,失败返回空pclose(): on success, returns the exit status of the command; if wait4(2) returns an error, or some other error is detected, -1 is returned.Both functions set errno to an appropriate value in the case of an error.// 一个线程执行fork就相当于当前进程创建子进程。

1.10 fgets

// man fgets
NAMEfgetc, fgets, getc, getchar, ungetc - input of characters and strings
SYNOPSIS#include <stdio.h>char *fgets(char *s, int size, FILE *stream);
// 返回值
RETURN VALUEfgets() returns s on success, and NULL on error or when end of file occurs while no characters have been read.// 读取失败返回NULL

2. EchoServer

Linux: This repository is specifically designed to store Linux code - Gitee.comhttps://gitee.com/Axurea/linux/tree/master/2025_05_26_EchoServer

3. 多线程远程命令执行

Linux: This repository is specifically designed to store Linux code - Gitee.comhttps://gitee.com/Axurea/linux/tree/master/2025_05_28_CommandServerTcp

4. 引入线程池版本翻译

  • 上篇UDP部分写过类似的设计方案。
  • 后面我们还会涉及http相关内容,到时候在引入线程池会更方便,也很合理。

5. 验证TCP - windows作为client访问Linux

Linux: This repository is specifically designed to store Linux code - Gitee.comhttps://gitee.com/Axurea/linux/tree/master/2025_05_28_Tcp_WindowsClient&&LinxuServer

注意:一定要开放云服务器对应的端口号,在你的阿里云或者腾讯云、华为云的网站后台中开放。

我们可以发现tcp client(windows)和tcp server(Linux)可以通信。

WinSock2.h是Windows Sockets API(应用程序接口)的头文件,用于在Windows平台上进行网络编程。它包含了Windows Sockets 2(WinSock2)所需的数据类型、函数声明和结构定义,使得开发者能够创建和使用套接字(sockets)进行网络通信。
在编写使用Winsock2的程序时,需要在源文件中包含WinSock2.h头文件。这样,编译器就能够识别并理解Winsock2中定义的数据类型和函数,从而能够正确的编译和链接网络相关的代码。
此外,与WinSock2.h头文件相对应的是ws2_32.lib库文件。在链接阶段,需要将这个库文件链接到程序中,以确保运行时能够找到并调用Winsock2 API中实现的函数。
在WinSock2.h中定义了一些重要的数据类型和函数,如:
WSADATA:保存初始化Winsock库时返回的信息。
SOCKET:表示一个套接字描述符,用于在网络中唯一标识一个套接字。
sockaddr_in:IPv4地址结构体,用于存储IP地址和端口号等信息。
socket():创建一个套接字。
bind():将套接字与本地地址绑定。
listen():将套接字设置为监听模式,等待客户端的连接请求。
accept():接受客户端的连接请求,并返回一个新的套接字描述符,用于与客户端
进行通信。


WSAStartup函数是Windows Sockets API的初始化函数,它用于初始化Winsock库。该函数在应用程序或DLL调用任何Windows套接字函数之前必须首先执行,它扮演着初始化的角色。
以下是WSAStartup函数的一些关键的:
它接受两个参数:wVersionRequested和IpWSAData。wVersionRequested用于指定所请求的Winsock版本,通常使用MAKEWORD(major,minor)宏,其中major和minor分别标识请求的主版本号和次版本号。IpWSAData是一个指向WSAData结构的指针用于接收初始化信息。
如果函数调用成功,它会返回0:否则,返回错误代码。
WSAStartup函数的主要作用是向操作系统说明我们将使用哪个版本的Winsock库,从而使得该库文件能与当前的操作系统协同工作。成功调用该函数后,Winsock库的状态会被初始化,应用程序就可以使用Winsock提供的一系列套接字服务,如地址家族识别、地址转换、名字查询和连接控制等。这些服务使得应用程序可以与底层的网络协议栈进行交互,实现网络通信。
在调用WSAStartup函数后,如果应用程序完成了对请求的Socket库的使用,应调用
WSAStartup函数后,如果应用程序完成了对请求的Socket库的使用,应调用WSACleanup
函数来解除与Socket库的绑定并释放所占用的系统资源。

6. connect的断线重连

客户端会面临服务器崩溃的情况,我们可以试着写一个客户端重连的代码,模拟并理解一些客户端行为,比如游戏客户端等。

采用状态机,实现一个简单的tcp client可以实现重连的效果。

Linux: This repository is specifically designed to store Linux code - Gitee.comhttps://gitee.com/Axurea/linux/tree/master/2025_05_28_TcpClientConnect


http://www.hkcw.cn/article/DZIiSwEIWB.shtml

相关文章

SmolVLM2: The Smollest Video Model Ever(七)

编写测试代码与评价指标 现在的数据集里面只涉及tool的分类和手术phase的分类&#xff0c;所以编写的评价指标还是那些通用的&#xff0c;但是&#xff1a; predicted_labels:[The current surgical phase is CalotTriangleDissection, Grasper, Hook tool exists., The curre…

Cancer Cell丨肺癌早期干预新突破,TIM-3靶点或成关键

2025年5月8日&#xff0c;Cancer Cell 在线发表了一篇来自美国MD安德森癌症中心的研究文章Spatial and multiomics analysis of human and mouse lung adenocarcinoma precursors reveals TIM-3 as a putative target for precancer interception。作者整合了空间蛋白组、转录组…

全志V853挂载sd卡

参考文章:https://blog.csdn.net/weixin_59351001/article/details/127102440 1、插上sd卡 fdisk -l2、挂载SD卡到开发板 mount /dev/mmcblk1p1 /mnt/sdcard挂载失败(如下报错),需要格式化SD卡再进行挂载

性能测试-jmeter实战1

课程&#xff1a;B站大学 记录软件测试-性能测试学习历程、掌握前端性能测试、后端性能测试、服务端性能测试的你才是一个专业的软件测试工程师 性能测试-jmeter实战1 为什么需要性能测试呢&#xff1f;性能测试的作用&#xff1f;性能测试体系性能测试基础性能测试工具性能监控…

PABD 2025:大数据与智慧城市管理的融合之道

会议简介 2025年公共管理与大数据国际会议&#xff08;ICPMBD 2025&#xff09;确实在海口举办。本次会议将围绕公共管理与大数据的深度融合、数据分析在公共管理中的应用、大数据驱动的政策制定与优化等议题展开深入研讨。参会者将有机会聆听前沿学术报告&#xff0c;分享研究…

DL00924-基于深度学习YOLOv11的工程车辆目标检测含数据集

文末有代码完整出处 &#x1f697; 基于深度学习YOLOv11的工程车辆目标检测——引领智能识别新潮流&#xff01; &#x1f680; 随着人工智能技术的飞速发展&#xff0c; 目标检测 已经在各个领域取得了显著突破&#xff0c;尤其是在 工程车辆识别 这一关键技术上。今天&#…

Java 对接 Office 365 邮箱全攻略:OAuth2 认证 + JDK8 兼容 + Spring Boot 集成(2025 版)

&#x1f6a8; 重要通知&#xff1a;微软强制 OAuth2&#xff0c;传统认证已失效&#xff01; 2023 年 10 月起&#xff0c;Office 365 全面禁用用户名 密码认证&#xff0c;Java 开发者必须通过OAuth 2.0实现邮件发送。本文针对 CSDN 技术栈&#xff0c;提供从 Azure AD 配置…

秒杀/高并发解决方案+落地实现

前面我们防止超卖 是通过到数据库查询和到数据库抢购,来完成的, 代码如下:如果在短时间内,大量抢购冲击 DB, 造成洪峰, 容易压垮数据库解决方案:使用 Redis 完成预减库存,如果没有库存了,直接返回,减小对 DB 的压力。图示:Redis 的预减,已经存在了原子性,就是一条一条…

Baklib企业知识激活解决方案

Baklib知识中台构建路径 Baklib通过模块化架构设计与智能数据治理双轮驱动&#xff0c;为企业构建知识中台提供标准化实施路径。首先基于自然语言处理&#xff08;NLP&#xff09;技术实现非结构化文档的语义解析&#xff0c;打通CRM、ERP等业务系统间的数据孤岛&#xff1b;随…

【Gemini 深度研究】人形机器人:最新开发方案与未来展望 (2024-2025)

Gemini根据深度研究报告自动生成的html网页录屏 人形机器人&#xff1a;最新开发方案与未来展望 (2024-2025) I. 执行摘要 2024年至2025年&#xff0c;人形机器人正处于从科研探索向实际应用转型的关键时期&#xff0c;其作为通用型机器人的潜力日益显现。这一转变主要得益于具…

【动态规划:斐波那契数列模型】第 N 个泰波那契数

1、第 N 个泰波那契数&#xff08;easy&#xff09; 1137. 第 N 个泰波那契数 泰波那契序列 Tn 定义如下&#xff1a; ​ T0 0, T1 1, T2 1, 且在 n > 0 的条件下 Tn3 Tn Tn1 Tn2。给你整数 n&#xff0c;请返回第 n 个泰波那契数 Tn 的值。 示例 1&#xff1a; …

秋招Day11 - JVM - JVM调优

性能监控的命令行工具&#xff1f; 操作系统层面&#xff1a; 我用过top来查看cpu和内存的使用情况使用过vmstat查看过虚拟内存的统计信息使用过iostat查看过系统的io情况使用过netstat查看过系统的网络信息 JDK自带的命令层面&#xff0c;我使用过&#xff1a; jmap -heap…

ChatGPT Plus/Pro 订阅教程(支持支付宝)

订阅 ChatGPT Plus GPT-4 最简单&#xff0c;成功率最高的方案 1. 登录 chat.openai.com 依次点击 Login &#xff0c;输入邮箱和密码 2. 点击升级 Upgrade 登录自己的 OpenAI 帐户后&#xff0c;点击左下角的 Upgrade to Plus&#xff0c;在弹窗中选择 Upgrade plan。 如果…

【深度学习】12. VIT与GPT 模型与语言生成:从 GPT-1 到 GPT4

VIT与GPT 模型与语言生成&#xff1a;从 GPT-1 到 GPT4 本教程将介绍 GPT 系列模型的发展历程、结构原理、训练方式以及人类反馈强化学习&#xff08;RLHF&#xff09;对生成对齐的改进。内容涵盖 GPT-1、GPT-2、GPT-3、GPT-3.5&#xff08;InstructGPT&#xff09;、ChatGPT …

笔试模拟 day14

观前提醒&#xff1a; 笔试所有系列文章均是记录本人的笔试题思路与代码&#xff0c;从中得到的启发和从别人题解的学习到的地方&#xff0c;所以关于题目的解答&#xff0c;只是以本人能读懂为目标&#xff0c;如果大家觉得看不懂&#xff0c;那是正常的。如果对本文的某些知…

基于照片环境信息的AI定位技术:从原理到实战的深度解析

基于照片环境信息的AI定位技术&#xff1a;从原理到实战的深度解析 摘要 本文聚焦基于照片环境信息的AI定位技术&#xff0c;系统梳理其核心原理、技术实现路径及行业应用场景。结合多模态融合、深度学习优化等前沿技术&#xff0c;分析如何通过AI训练提升定位精度&#xff0c…

NumPy 2.x 完全指南【二十二】数组标量

文章目录 1. 标量&#xff08;Scalar &#xff09;2. 数组标量&#xff08;Array Scalar&#xff09;3. 标量类型3.1 基类3.1.1 generic3.1.2 number3.1.3 flexible 3.2 整数类型3.2.1 有符号整数3.2.2 无符号整数 3.3 不精确类型3.3.1 浮点数3.3.2 复数 3.4 其他类型3.4.1 布尔…

外地车在北京进京证用完后该如何行驶

外地车在北京进京证用完后该如何行驶 这个问题想必非京籍的车友都有这样的困惑吧 作为一名资深外地车主&#xff0c;已在北京漂泊了13年之久&#xff0c;12次进京证的办理根本不够用&#xff0c;也有网友支招说和家人来回过户200搞定&#xff0c;多出12次&#xff0c;奈何这种…

可靠数据传输原理

目录 构造可靠数据传输协议 一、rdt1.0&#xff1a;理想信道下的可靠传输 核心假设与功能 二、rdt 2.0&#xff1a;带差错检测的停等协议 核心假设与功能 三、rdt 2.1&#xff1a;修复 ACK/NAK 不可靠性 核心改进 四、rdt 2.2&#xff1a;纯 ACK 实现的可靠传输 核心改…

JAVA重症监护系统源码 ICU重症监护系统源码 智慧医院重症监护系统源码

智慧医院重症监护系统源码 ICU重症监护系统源码 开发语言&#xff1a;JavaVUE ICU护理记录&#xff1a;实现病人数据的自动采集&#xff0c;实时记录监护过程数据。支持主流厂家的监护仪、呼吸机等床旁数字化设备的数据采集。对接检验检查系统&#xff0c;实现自动化录入。喜…