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

news2024/11/20 11:24:00

文章目录

  • 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); // 绑定本机所有IP

if (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) { // 最大连接等待队列长度为5
    perror("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协议进行可靠的数据通信,并根据实际需求实现功能丰富的网络应用程序。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2166026.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

力扣每日一题 公司命名 集合 找规律

Problem: 2306. 公司命名 &#x1f468;‍&#x1f3eb; 灵神题解 class Solution {public long distinctNames(String[] ideas) {// 创建一个大小为26的HashSet数组&#xff0c;用于存储每个首字母对应的字符串集合Set<String>[] groups new HashSet[26];Arrays.set…

基于Python大数据的音乐推荐及数据分析可视化系统

作者&#xff1a;计算机学姐 开发技术&#xff1a;SpringBoot、SSM、Vue、MySQL、JSP、ElementUI、Python、小程序等&#xff0c;“文末源码”。 专栏推荐&#xff1a;前后端分离项目源码、SpringBoot项目源码、Vue项目源码、SSM项目源码 精品专栏&#xff1a;Java精选实战项目…

Cadence Allegro17.4 板框倒角

一、Cadence Allegro 板框倒角有倒斜角和倒圆角两种形式&#xff1a; 1、 板框倒斜角 2、 板框倒圆角 二、有些时候不能倒角 如果我们绘制的板框是Shape属性的是不能正常倒角设置&#xff0c;要将Shape属性的板框更改为lines属性的板框。 1、 选择菜单栏Shape——Decompose …

Wireshark_流量分析

在当今数字化的时代&#xff0c;网络流量分析对于确保网络的稳定运行、排查故障以及保障网络安全至关重要。Wireshark 作为一款功能强大的网络数据包分析工具&#xff0c;为我们提供了多种实用的功能&#xff0c;帮助我们深入了解网络中的数据传输情况。 1、数据包筛选 数据包…

HTTP和HTTPS的区别,HTTP协议转HTTPS协议测试需要注意内容

简单快捷&#xff1a;HTTP 相对于 HTTPS 更简单和快速。在开发过程中&#xff0c;可能频繁地修改代码并测试&#xff0c;使用 HTTP 可以减少一些开发中的额外步骤和复杂性。 不涉及敏感信息&#xff1a;在本地开发环境中&#xff0c;通常不涉及真实用户数据或敏感信息的传输&a…

单链表实现和数组模拟单链表

现在有一个排好序的若干个元素(升序),现在要插入一个元素啊&#xff0c;请你输入插入该元素后的序列(升序) 请分别用单链表实现&#xff0c;和数组模拟单链表实现 为什么要用数组模拟单链表 1.内存局部性&#xff1a;数组在内存中是连续存储的&#xff0c;因此在访问元素时可…

了解针对基座大语言模型(类似 ChatGPT 的架构,Decoder-only)的重头预训练和微调训练

&#x1f349; CSDN 叶庭云&#xff1a;https://yetingyun.blog.csdn.net/ 随着自然语言处理&#xff08;NLP&#xff09;技术的飞速进步&#xff0c;基于 Transformer 架构的大语言模型在众多任务中取得了显著成就。特别是 Decoder-only 架构&#xff0c;如 GPT 系列模型&…

“警警”有条:zCloud告警中心的告警与处置实践

ENMOTECH 随着金融行业数字化转型步伐的加快&#xff0c;海量数据处理成为常态&#xff0c;而作为数据存储和管理的核心——数据库的稳定性与效率直接影响着企业的运营成效。某金融科技企业使用了近10个品类、300余套数据库来承载业务&#xff0c;在专业运维、集中管理等方面都…

【操作系统】速成3

Linux内核和windows内核 原来鸿蒙是微内核 windows混合内核 参考&#xff1a;xiaolincoding.com

5种强大的方式:AI在临终关怀中提升护理质量,改善生活

目录 什么是临终关怀中的AI&#xff1f;AI如何个性化临终关怀&#xff1f;AI如何改善临终关怀患者的生活质量&#xff1f; 疼痛管理症状管理的预测分析情感和心理支持高效的资源分配减轻家庭压力 临终关怀中AI的未来 近年来&#xff0c;医疗保健行业在人工智能&#xff08;AI…

MySQL --事务(上)

文章目录 1.什么是事务1.1为什么会出现事务1.2 事务的版本支持1.3 事务提交方式1.4事务常见操作方式1.4.1正常演示 - 证明事务的开始与回滚1.4.2非正常演示1 - 证明未commit&#xff0c;客户端崩溃&#xff0c;MySQL自动会回滚&#xff08;隔离级别设置为读未提交&#xff09;1…

Ubuntu环境切换到服务器某个用户后source等命令和Tab快捷补全都用不了了,提示没找到,但root用户可以

以escs用户为例&#xff1a; 输入以下命令 grep root /etc/passwd grep escs /etc/passwd 对比发现&#xff0c;root用户配的是bash&#xff0c;而escs却是sh&#xff0c; 所以把escs的sh改成和root一样的bash&#xff0c;命令为 usermod -s /bin/bash escs 改好后就可以了。 …

Win11 安装 PostgreSQL 数据库,两种方式详细步骤

文章目录 一、exe文件安装 &#xff08;推荐&#xff09;下载安装包1. 选择操作系统2. 跳转到EDB&#xff08;PostgreSQL 的安装包托管在 EDB上&#xff09;3. 选择版本点击下载按钮 安装1. 管理员打开安装包2. 选择安装目录3. 勾选安装项4. 设置数据存储目录5. 设置管理员密码…

C语言线程编程深度解析

文章目录 前言一、线程基础概念1. 什么是线程&#xff1f;2. 线程与进程的区别 二、POSIX线程库&#xff08;pthread&#xff09;1. pthread简介2. 编译与链接3. 创建线程示例代码&#xff1a; 4. 线程同步互斥锁&#xff08;Mutex&#xff09;示例代码&#xff1a; 条件变量&a…

SpringBoot代码实战(MyBatis-Plus+Thymeleaf)

构建项目 修改pom.xml文件&#xff0c;添加其他依赖以及设置 <!--MyBatis-Plus依赖--><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-spring-boot3-starter</artifactId><version>3.5.6</version><…

智源研究院与百度达成战略合作 共建AI产研协同生态

2024年9月24日&#xff0c;北京智源人工智能研究院&#xff08;简称“智源研究院”&#xff09;与北京百度网讯科技有限公司&#xff08;简称“百度”&#xff09;正式签署战略合作协议&#xff0c;双方将充分发挥互补优势&#xff0c;在大模型等领域展开深度合作&#xff0c;共…

共享打印机无法创建打印作业原因分析及解决方法

在日常办公和生活中&#xff0c;打印机是不可或缺的重要设备。然而&#xff0c;有时在添加打印机的过程中&#xff0c;经常会遇各种问题。今天有个小伙伴问我在访问共享打印机时提示“无法创建打印作业”怎么回事&#xff1f;今天小编就教大家共享打印机无法创建打印作业原因分…

多表查询。

一、多表查询 select * from 表名,表名; select * from 表名,表名 where 条件; 二、内连接 隐式 select 字段列表 from 表1,表2 where 条件; 显示 select 字段列表 from 表1 INNER JOIN 表2 on 条件; 三、外连接 1.左外连接 select 字段列表 from 表1 left [outer] join 表…

接口自动化测试框架详解(pytest+allure+aiohttp+ 用例自动生成)

&#x1f345; 点击文末小卡片&#xff0c;免费获取软件测试全套资料&#xff0c;资料在手&#xff0c;涨薪更快 近期准备优先做接口测试的覆盖&#xff0c;为此需要开发一个测试框架&#xff0c;经过思考&#xff0c;这次依然想做点儿不一样的东西。 接口测试是比较讲究效…

【C++】STL--string(下)

1.string类对象的修改操作 erase&#xff1a;指定位置删除 int main() {string str1("hello world");str1.push_back(c);//尾插一个ccout << str1 << endl;string str2;str2.append("hello"); // 在str后追加一个字符"hello"cout…