当前位置: 首页 > news >正文

TCP网络编程概述、相关函数、及实现超详解

文章目录

  • TCP网络编程概述
    • 1. TCP协议的特点
    • 2. TCP与UDP的差异
    • 3. TCP编程流程
  • TCP网络编程相关函数详解
    • 1. `socket()`:创建套接字
      • 参数说明:
      • 返回值:
      • 示例:
    • 2. `connect()`:客户端连接服务器
      • 参数说明:
      • 返回值:
      • 示例:
    • 3. `bind()`:服务器绑定地址和端口
      • 参数说明:
      • 返回值:
      • 示例:
    • 4. `listen()`:监听连接请求
      • 参数说明:
      • 返回值:
      • 示例:
    • 5. `accept()`:接受客户端连接
      • 参数说明:
      • 返回值:
      • 示例:
    • 6. `send()`:发送数据
      • 参数说明:
      • 返回值:
      • 示例:
    • 7. `recv()`:接收数据
      • 参数说明:
      • 返回值:
      • 示例:
    • 8. `close()`:关闭连接
      • 参数说明:
      • 返回值:
      • 示例:
  • TCP客户端与服务端的实现案例
    • TCP客户端实现
    • TCP服务器实现


TCP网络编程概述

TCP(Transmission Control Protocol,传输控制协议)是一种面向连接的传输层协议,广泛应用于网络通信。与UDP(User Datagram Protocol,用户数据报协议)不同,TCP提供了可靠的数据传输机制,确保数据能够完整、有序地从发送端传输到接收端。本文将详细介绍TCP协议的特点、TCP与UDP的差异、TCP编程流程以及客户端和服务器的实现方式。

1. TCP协议的特点

TCP具有以下主要特点:

  1. 面向连接:在通信前,TCP必须先建立连接。
  2. 有序号和确认机制:每个数据包都带有序号,接收方需要发送确认序号,确保数据有序接收。
  3. 排序、检错和失败重传:TCP对接收到的数据进行排序,检查数据的完整性,如有错误,会进行重传。
  4. 大文件传输:由于TCP能够分片并重新组装数据包,它特别适合大文件的可靠传输。
  5. 不支持广播和多播:与UDP不同,TCP不支持广播和多播,只支持点对点通信。

在TCP通信中,客户端和服务器的角色各不相同:

  • TCP客户端:主动向服务器发起连接。
  • TCP服务器:被动等待客户端连接。

2. TCP与UDP的差异

特点TCPUDP
面向连接
可靠传输
顺序保证
传输效率较低(需要连接、确认等)较高(无连接、无确认)
数据传输大小限制有(单个数据包有限制)
广播/多播支持

TCP更适合需要可靠传输的应用场景,如文件传输、邮件等,而UDP更适合实时性要求高的应用,如视频、语音传输。

3. TCP编程流程

编写TCP程序时,主要流程如下:

  1. 创建套接字:使用socket()函数创建TCP套接字。
  2. 连接服务器(客户端)或绑定端口监听连接(服务器)。
  3. 发送或接收数据:通过send()recv()函数进行数据交换。
  4. 关闭连接:使用close()函数关闭套接字。
    在这里插入图片描述

TCP网络编程相关函数详解

在编写TCP程序时,通常会使用一系列网络函数来创建套接字、建立连接、发送/接收数据并关闭连接。下面将对TCP网络编程中常用的函数进行详细讲解,以帮助读者更好地理解每个函数的用途及其使用方法。

1. socket():创建套接字

socket()函数是网络编程的基础,用于创建套接字(Socket)。套接字是网络通信的端点,类似于两台设备之间的通信通道。它的定义如下:

int socket(int domain, int type, int protocol);

参数说明:

  • domain:指定通信使用的地址族,常用的有:
    • AF_INET:IPv4网络协议。
    • AF_INET6:IPv6网络协议。
  • type:指定套接字类型,常用的有:
    • SOCK_STREAM:流式套接字,用于TCP连接。
    • SOCK_DGRAM:数据报套接字,用于UDP连接。
  • protocol:一般为0,表示使用默认协议(TCP或UDP)。

返回值:

  • 成功:返回套接字的文件描述符。
  • 失败:返回-1,并设置errno

示例:

int sock = socket(AF_INET, SOCK_STREAM, 0); // 创建TCP套接字
if (sock < 0) {perror("socket creation failed");
}

2. connect():客户端连接服务器

connect()函数用于客户端主动向服务器发起连接请求。在TCP连接中,客户端通过该函数连接指定的服务器。

int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);

参数说明:

  • sockfd:客户端套接字描述符。
  • addr:服务器的地址结构,通常为struct sockaddr_in
  • addrlen:地址结构的大小。

返回值:

  • 成功:返回0。
  • 失败:返回-1,并设置errno

示例:

struct sockaddr_in server_addr;
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(8000); // 服务器端口号
server_addr.sin_addr.s_addr = inet_addr("10.35.184.221"); // 服务器IP地址if (connect(sock, (struct sockaddr *)&server_addr, sizeof(server_addr)) != 0) {perror("connect failed");
}

3. bind():服务器绑定地址和端口

bind()函数用于将套接字绑定到指定的IP地址和端口号。服务器需要通过bind()来指定其服务的地址和端口。

int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);

参数说明:

  • sockfd:服务器套接字描述符。
  • addr:服务器地址结构,通常为struct sockaddr_in
  • addrlen:地址结构的大小。

返回值:

  • 成功:返回0。
  • 失败:返回-1,并设置errno

示例:

struct sockaddr_in server_addr;
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(9000); // 绑定端口9000
server_addr.sin_addr.s_addr = htonl(INADDR_ANY); // 绑定本机所有IPif (bind(sock, (struct sockaddr *)&server_addr, sizeof(server_addr)) != 0) {perror("bind failed");
}

4. listen():监听连接请求

服务器通过listen()函数来监听客户端的连接请求,进入监听状态,准备接受客户端的连接。

int listen(int sockfd, int backlog);

参数说明:

  • sockfd:服务器套接字描述符。
  • backlog:连接队列的大小,表示服务器可以处理的等待连接的客户端数量。

返回值:

  • 成功:返回0。
  • 失败:返回-1,并设置errno

示例:

if (listen(sock, 5) != 0) { // 最大连接等待队列长度为5perror("listen failed");
}

5. accept():接受客户端连接

accept()函数用于服务器从连接队列中取出一个客户端连接,生成一个新的套接字,用于和该客户端进行通信。

int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);

参数说明:

  • sockfd:服务器监听套接字。
  • addr:客户端地址结构,用于存储连接的客户端信息。
  • addrlen:地址结构的大小。

返回值:

  • 成功:返回一个新的已连接套接字描述符,用于与客户端通信。
  • 失败:返回-1,并设置errno

示例:

struct sockaddr_in client_addr;
socklen_t client_len = sizeof(client_addr);
int client_sock = accept(sock, (struct sockaddr *)&client_addr, &client_len);
if (client_sock < 0) {perror("accept failed");
}

6. send():发送数据

send()函数用于向指定的套接字发送数据。

ssize_t send(int sockfd, const void *buffer, size_t length, int flags);

参数说明:

  • sockfd:套接字描述符。
  • buffer:指向需要发送数据的缓冲区。
  • length:要发送的数据长度。
  • flags:通常为0,可选其他标志位。

返回值:

  • 成功:返回发送的字节数。
  • 失败:返回-1,并设置errno

示例:

char message[] = "Hello, TCP Server!";
if (send(sock, message, strlen(message), 0) < 0) {perror("send failed");
}

7. recv():接收数据

recv()函数用于从指定的套接字接收数据。

ssize_t recv(int sockfd, void *buffer, size_t length, int flags);

参数说明:

  • sockfd:套接字描述符。
  • buffer:指向接收数据的缓冲区。
  • length:缓冲区大小。
  • flags:通常为0,可选其他标志位。

返回值:

  • 成功:返回接收到的字节数。
  • 失败:返回-1,并设置errno
  • 如果连接被关闭,返回0。

示例:

char buffer[128];
ssize_t bytes_received = recv(sock, buffer, sizeof(buffer), 0);
if (bytes_received > 0) {buffer[bytes_received] = '\0'; // 确保数据是以字符串形式输出printf("Received data: %s\n", buffer);
} else if (bytes_received == 0) {printf("Connection closed by peer\n");
} else {perror("recv failed");
}

8. close():关闭连接

close()函数用于关闭指定的套接字,释放相关资源。

int close(int sockfd);

参数说明:

  • sockfd:需要关闭的套接字描述符。

返回值:

  • 成功:返回0。
  • 失败:返回-1,并设置errno

示例:

close(sock); // 关闭套接字

TCP客户端与服务端的实现案例

TCP客户端实现

在TCP客户端编程中,客户端主动发起与服务器的连接。以下是一个基本的TCP客户端代码示例:

#include <arpa/inet.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>typedef struct sockaddr_in addr_in;
typedef struct sockaddr addr;int main(int argc, char const *argv[]) {// 创建TCP套接字int sock = socket(AF_INET, SOCK_STREAM, 0);// 连接TCP服务器addr_in server_addr;server_addr.sin_family = AF_INET;server_addr.sin_port = htons(8000);server_addr.sin_addr.s_addr = inet_addr("10.35.184.221");if (connect(sock, (addr *)&server_addr, sizeof(server_addr)) != 0) {perror("connect");return -1;}printf("TCP server connect OK\n");// 每2秒发送一次数据int n = 0;while (1) {char data[] = "hi, tcp server!";if (send(sock, data, strlen(data), 0) > 0) {printf("(%d)发送成功!\n", ++n);}sleep(2);}close(sock);return 0;
}

TCP服务器实现

TCP服务器是被动的,等待客户端连接。在实现中,服务器需要首先绑定地址并监听客户端连接,接着通过accept()函数接受客户端的连接。以下是一个简单的单聊TCP服务器实现:

#include <arpa/inet.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <pthread.h>
#include <stdlib.h>typedef struct sockaddr_in addr_in;
typedef struct sockaddr addr;typedef struct {int sock;char ip[INET_ADDRSTRLEN];
} client_info;void *readTask(void *arg) {client_info *info = (client_info *)arg;while (1) {char buf[128] = "";ssize_t len = recv(info->sock, buf, 128, 0);if (len > 0) {printf("%s: %s\n", info->ip, buf);}}
}void *sendTask(void *arg) {client_info *info = (client_info *)arg;while (1) {char buf[128] = "";fgets(buf, 128, stdin);buf[strlen(buf)-1] = 0;send(info->sock, buf, strlen(buf), 0);if (strncmp(buf, "bye", 3) == 0) break;}
}int main(int argc, char const *argv[]) {if (argc != 2) return -1;// 创建TCP套接字int sock = socket(AF_INET, SOCK_STREAM, 0);// 设置服务器地址addr_in server_addr;server_addr.sin_family = AF_INET;server_addr.sin_port = htons(atoi(argv[1]));server_addr.sin_addr.s_addr = htonl(INADDR_ANY);if (bind(sock, (addr *)&server_addr, sizeof(server_addr)) != 0) {perror("bind");return -1;}listen(sock, 1000);printf("TCP server running\n");addr_in client_addr;socklen_t client_addr_len = sizeof(client_addr);int client_sock = accept(sock, (addr *)&client_addr, &client_addr_len);if (client_sock > 0) {client_info info;info.sock = client_sock;inet_ntop(AF_INET, &client_addr.sin_addr, info.ip, INET_ADDRSTRLEN);printf("Client connected: %s\n", info.ip);pthread_t read_tid, send_tid;pthread_create(&read_tid, NULL, readTask, &info);pthread_create(&send_tid, NULL, sendTask, &info);pthread_join(send_tid, NULL);}close(sock);return 0;
}

通过上述TCP网络编程的介绍和实例代码,读者可以掌握如何使用TCP协议进行可靠的数据通信,并根据实际需求实现功能丰富的网络应用程序。

相关文章:

TCP网络编程概述、相关函数、及实现超详解

文章目录 TCP网络编程概述1. TCP协议的特点2. TCP与UDP的差异3. TCP编程流程 TCP网络编程相关函数详解1. socket()&#xff1a;创建套接字参数说明&#xff1a;返回值&#xff1a;示例&#xff1a; 2. connect()&#xff1a;客户端连接服务器参数说明&#xff1a;返回值&#x…...

Cluade 3.5 Sonnet 提示词泄露

prompt 翻译&#xff1a; The notebook currently demonstrates support for a two agent setup. Support for GroupChat is currently in development....

git clone代码报错Permission denied (publickey)

git clone gerrit SSH的Clone with commit-msg hook代码连接&#xff0c;报错Permission denied (publickey). 一般在C:\Users\用户名.ssh文件夹下有一个id_rsa.pub文件 把文件里的内容复制 到gerrit网站上User Settings的SSH keys里 在New SSH key里粘贴刚刚复制的内容&…...

QT设计中文输入法软键盘DLL给到C#开发步骤

开发目的&#xff1a;本文提供解决触摸屏C#程序中无法输入中文问题&#xff0c;中文拼音采用开源的谷歌输入法程序、使用QT编译中文输入法界面和中文输入法接口给到C#使用。 开发步骤&#xff1a; 1、QT中设计字母和字符输入界面 2、QT中设计数字输入界面 3、QT中封装调用谷歌…...

使用 Rust 和 wasm-pack 开发 WebAssembly 应用

一、什么是 WebAssembly&#xff1f; WebAssembly 是一种运行在现代 Web 浏览器中的新型二进制指令格式。它是一种低级别的字节码&#xff0c;可以被多种语言编译&#xff0c;并在浏览器中高效运行。 1.1 WebAssembly 的背景与概念 高性能计算&#xff1a;WebAssembly 旨在提…...

1. IP地址介绍

IP地址 一、网络概述1、网络类型2、网络组成、传输介质2.1 组成2.2 传输介质 二、IP地址1、IP地址的表示方法2、IP地址的组成3、IP地址的类型3.1 根据IP地址第一个字节大小来分3.1.1 单播地址 Unicast 3.2 根据IP地址的使用 三、子网掩码 netmask1、默认的子网掩码2、判断多个I…...

喜报来袭~又有一波优秀企业选择Smartbi

近期&#xff0c;大金&#xff08;中国&#xff09;武汉&广州分公司、中广核智能、新疆银行、四川省人民医院等多家知名企业/机构签约Smartbi&#xff0c;数智化建设再上新高度&#xff01; Smartbi数10年专注于商业智能BI与大数据分析软件与服务&#xff0c;为各行各业提…...

Web端云剪辑解决方案,BS架构私有化部署,安全可控

传统视频制作流程繁琐、耗时&#xff0c;且对专业设备和软件的高度依赖&#xff0c;常常让企业望而却步&#xff0c;美摄科技凭借其强大的技术实力和创新能力&#xff0c;推出了面向企业用户的Web端云剪辑解决方案&#xff0c;为企业提供一站式、高效、便捷的视频生产平台。 B…...

AI 代码助手插件推荐

AI正在重塑我们的工作方式&#xff0c;软件开发也不例外。AI编码助手使开发人员能够比以往更快、更有效地编写代码。 在本文中&#xff0c;我们将比较几个个最好的AI编码助手&#xff0c;突出它们的独特功能和价格&#xff0c;以帮助读者找到完美的编码伙伴: 1、腾讯云 AI 代…...

word中的表格全部设置宽度100%

1、背景 我们用工具将数据库或其他的数据导出成word时&#xff0c;表格有的会大于100%&#xff0c;超过了边界。word没有提供全局修改的方法。如果我们想改成100%。 一种方式是通过宏&#xff0c;全局改。一种是手动改。 2、宏修改 如果表格多&#xff0c;可以通过这种方式。…...

JFinal整合Websocket

学习笔记&#xff0c;供大家参考 总结的不错的话&#xff0c;记得点赞收藏关注哦&#xff01;导入JAR包 javax.websocket-api <dependency><groupId>javax.websocket</groupId><artifactId>javax.websocket-api</artifactId><version>1.1&…...

(done) 声音信号处理基础知识(7) (Understanding Time Domain Audio Features)

参考&#xff1a;https://www.youtube.com/watch?vSRrQ_v-OOSg&t1s 时域特征包括&#xff1a; 1.幅度包络 2.均方根能量 3.过零率 振幅包络的定义&#xff1a;一个 frame 里&#xff0c;所有采样点中最大的振幅值 一个形象的关于振幅包络的可视化解释如下&#xff1a;…...

拓数派荣获上海数据交易所“数据治理服务商”认证

近期&#xff0c;杭州拓数派科技发展有限公司&#xff08;以下简称“拓数派”&#xff09;荣获上海数据交易所“数据治理服务商”认证&#xff0c;标志着拓数派正式加入上海数据交易所数商生态&#xff0c;成为上海数据交易所官方认证的数据治理服务商。拓数派企业发展部总监吴…...

【Redis】分布式锁之 Redission

一、基于setnx实现的分布式锁问题 重入问题&#xff1a;获得锁的线程应能再次进入相同锁的代码块&#xff0c;可重入锁能防止死锁。例如在HashTable中&#xff0c;方法用synchronized修饰&#xff0c;若在一个方法内调用另一个方法&#xff0c;不可重入会导致死锁。而synchroni…...

对象序列化

Data AllArgsConstructor NoArgsConstructor public class Product implements Serializable {public Long productId;public String productName;public Double productPrice;public String productImg;public Integer productStatus;public String productCategory; }为什么要…...

什么是专利开放许可?

专利作为技术创新的重要载体&#xff0c;其有效转化与应用成为推动社会进步和经济发展的关键力量。那么&#xff0c;专利开放许可究竟是何方神圣&#xff1f;它如何打破传统专利许可的壁垒&#xff0c;促进创新资源的广泛共享&#xff1f; 专利开放许可的定义 专利开放许可&am…...

地表最强开源大模型!Llama 3.2,如何让你的手机变身私人智能助理

你有没有想过&#xff0c;为什么现在的手机越来越像小型电脑&#xff1f;无论是拍照、看视频&#xff0c;还是用各种APP&#xff0c;甚至是AI助手&#xff0c;手机的功能几乎无所不能。其实&#xff0c;这一切的背后有一个技术正在悄悄改变我们的生活&#xff0c;那就是Llama 3…...

Pandas中DataFrame表格型数据结构

目录 1、DataFrame是什么2、创建一个dataframe3、获取dataframe的行、列索引4、获取dataframe的值 1、DataFrame是什么 series是有一组数据与一组索引&#xff08;行索引&#xff09;组成的数据结构&#xff0c;而dataframe是由一组数据与一对索引&#xff08;行索引和列索引&…...

C++的智能指针

很久之前&#xff0c;我们说到了new和delete关键字。 new在堆上分配内存&#xff0c;需要delete来删除内存、释放内存&#xff0c;因为它不会自动释放内存。 智能指针是实现过程自动化的一种方式&#xff0c;即当我们调用new时&#xff0c;我们不需要调用delete关键字。 在很…...

微信小程序showLoading ,showToast ,hideLoading连续调用出现showLoading 不关闭的情况记录

wx.showLoading({title: "操作中",mask: true,});api().then(() > {wx.showToast({title: "操作成功",icon: "none",});}).finally(() > {wx.hideLoading();}); 类似的代码偶尔会出现showLoading不关闭的现象, 这种情况下的解决方法就是 …...

网络编程(Modbus进阶)

思维导图 Modbus RTU&#xff08;先学一点理论&#xff09; 概念 Modbus RTU 是工业自动化领域 最广泛应用的串行通信协议&#xff0c;由 Modicon 公司&#xff08;现施耐德电气&#xff09;于 1979 年推出。它以 高效率、强健性、易实现的特点成为工业控制系统的通信标准。 包…...

C++_核心编程_多态案例二-制作饮品

#include <iostream> #include <string> using namespace std;/*制作饮品的大致流程为&#xff1a;煮水 - 冲泡 - 倒入杯中 - 加入辅料 利用多态技术实现本案例&#xff0c;提供抽象制作饮品基类&#xff0c;提供子类制作咖啡和茶叶*//*基类*/ class AbstractDr…...

QMC5883L的驱动

简介 本篇文章的代码已经上传到了github上面&#xff0c;开源代码 作为一个电子罗盘模块&#xff0c;我们可以通过I2C从中获取偏航角yaw&#xff0c;相对于六轴陀螺仪的yaw&#xff0c;qmc5883l几乎不会零飘并且成本较低。 参考资料 QMC5883L磁场传感器驱动 QMC5883L磁力计…...

江苏艾立泰跨国资源接力:废料变黄金的绿色供应链革命

在华东塑料包装行业面临限塑令深度调整的背景下&#xff0c;江苏艾立泰以一场跨国资源接力的创新实践&#xff0c;重新定义了绿色供应链的边界。 跨国回收网络&#xff1a;废料变黄金的全球棋局 艾立泰在欧洲、东南亚建立再生塑料回收点&#xff0c;将海外废弃包装箱通过标准…...

华为OD机试-食堂供餐-二分法

import java.util.Arrays; import java.util.Scanner;public class DemoTest3 {public static void main(String[] args) {Scanner in new Scanner(System.in);// 注意 hasNext 和 hasNextLine 的区别while (in.hasNextLine()) { // 注意 while 处理多个 caseint a in.nextIn…...

DBAPI如何优雅的获取单条数据

API如何优雅的获取单条数据 案例一 对于查询类API&#xff0c;查询的是单条数据&#xff0c;比如根据主键ID查询用户信息&#xff0c;sql如下&#xff1a; select id, name, age from user where id #{id}API默认返回的数据格式是多条的&#xff0c;如下&#xff1a; {&qu…...

uniapp微信小程序视频实时流+pc端预览方案

方案类型技术实现是否免费优点缺点适用场景延迟范围开发复杂度​WebSocket图片帧​定时拍照Base64传输✅ 完全免费无需服务器 纯前端实现高延迟高流量 帧率极低个人demo测试 超低频监控500ms-2s⭐⭐​RTMP推流​TRTC/即构SDK推流❌ 付费方案 &#xff08;部分有免费额度&#x…...

第 86 场周赛:矩阵中的幻方、钥匙和房间、将数组拆分成斐波那契序列、猜猜这个单词

Q1、[中等] 矩阵中的幻方 1、题目描述 3 x 3 的幻方是一个填充有 从 1 到 9 的不同数字的 3 x 3 矩阵&#xff0c;其中每行&#xff0c;每列以及两条对角线上的各数之和都相等。 给定一个由整数组成的row x col 的 grid&#xff0c;其中有多少个 3 3 的 “幻方” 子矩阵&am…...

Python 包管理器 uv 介绍

Python 包管理器 uv 全面介绍 uv 是由 Astral&#xff08;热门工具 Ruff 的开发者&#xff09;推出的下一代高性能 Python 包管理器和构建工具&#xff0c;用 Rust 编写。它旨在解决传统工具&#xff08;如 pip、virtualenv、pip-tools&#xff09;的性能瓶颈&#xff0c;同时…...

HarmonyOS运动开发:如何用mpchart绘制运动配速图表

##鸿蒙核心技术##运动开发##Sensor Service Kit&#xff08;传感器服务&#xff09;# 前言 在运动类应用中&#xff0c;运动数据的可视化是提升用户体验的重要环节。通过直观的图表展示运动过程中的关键数据&#xff0c;如配速、距离、卡路里消耗等&#xff0c;用户可以更清晰…...