102.套接字-Socket网络编程4(TCP通信流程)

news2024/11/28 8:23:07

目录

TCP编程流程

 套接字函数

1.创建套接字

2.绑定地址

3.监听连接请求

4.接受连接

5. 连接到服务器

6. 发送数据

7. 接收数据

8.关闭套接字

服务器端通信流程 

示例代码

客户端通信流程

代码示例


TCP编程流程

TCP是一个面向连接的,安全的,流式传输协议,这个协议是一个传输层协议。

  • 面向连接:是一个双向连接,通过三次握手完成,断开连接需要通过四次挥手完成。
  • 安全:tcp通信过程中,会对发送的每一数据包都会进行校验, 如果发现数据丢失, 会自动重传
  • 流式传输:发送端和接收端处理数据的速度,数据的量都可以不一致。

TCP 的服务器端和客户端编程流程如下: 

 套接字函数

        套接字编程中,常用的套接字函数通常涵盖套接字的创建、绑定、监听、连接、发送、接收、关闭等操作。以下是一些常用的套接字函数,这些函数通常在C语言的<sys/socket.h>头文件中声明:

1.创建套接字

int socket(int domain, int type, int protocol);
  • 参数:

    • domain:使用的地址协议族,如 AF_INET、AF_INET6分别表示IPv4、IPv6格式。
    • type:套接字类型,如 SOCK_STREAM(流式传输协议)表示TCP套接字,SOCK_DGRAM(报式传输协议)表示UDP套接字。
    • protocol:通常为0,表示自动选择协议。
  • 返回值:

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

2.绑定地址

// 将文件描述符和本地的IP与端口进行绑定   
int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
  • 参数:

    • sockfd:套接字的文件描述符,通过socket调用得到的返回值。
    • addr:包含要绑定的IP地址和端口号的结构体。
    • addrlenaddr 结构体的大小,sizeof(addr)。
  • 返回值:

    • 成功:0,失败:返回-1。

3.监听连接请求

// 给监听的套接字设置监听
int listen(int sockfd, int backlog);
  • 参数:

    • sockfd:套接字的文件描述符,通过socket调用得到的返回值。
    • backlog:在进入队列中等待接受的最大连接数,最大值为128。
  • 返回值:

    • 成功:0,失败:返回-1。

4.接受连接

// 等待并接受客户端的连接请求, 建立新的连接, 会得到一个新的文件描述符(通信的)		
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
  • 参数:

    • sockfd:套接字的文件描述符。
    • addr:用于存储客户端地址信息的结构体。
    • addrlenaddr 结构体的大小。
  • 返回值:

    • 函数调用成功,得到一个文件描述符, 用于和建立连接的这个客户端通信,调用失败返回 -1。

这个函数是一个阻塞函数,当没有新的客户端连接请求的时候,该函数阻塞;当检测到有新的客户端连接请求时,阻塞解除,新连接就建立了,得到的返回值也是一个文件描述符,基于这个文件描述符就可以和客户端通信了。

5. 连接到服务器

// 成功连接服务器之后, 客户端会自动随机绑定一个端口
// 服务器端调用accept()的函数, 第二个参数存储的就是客户端的IP和端口信息
int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
  • 参数:

    • sockfd:套接字的文件描述符,通过socket调用得到的返回值。
    • addr:用于存储客户端地址信息的结构体,这个IP和端口也需要转换为大端然后再赋值。
    • addrlenaddr 结构体的大小。
  • 返回值:

    • 连接成功返回0,连接失败返回-1

6. 发送数据

ssize_t send(int sockfd, const void *buf, size_t len, int flags);
  • 参数:

    • sockfd:套接字的文件描述符。
    • buf:包含要发送数据的缓冲区。
    • len:要发送的数据的长度。
    • flags:发送标志,通常为0。
  • 返回值:

    • 成功:返回发送的字节数。
    • 失败:返回-1。

7. 接收数据

ssize_t recv(int sockfd, void *buf, size_t len, int flags);
  • 参数:

    • sockfd:套接字的文件描述符。
    • buf:用于接收数据的缓冲区。
    • len:要接收的数据的长度。
    • flags:接收标志,通常为0。
  • 返回值:

    • 成功:返回接收的字节数。
    • 失败:返回-1。

8.关闭套接字

int close(int sockfd);
  • 参数:

    • sockfd:套接字的文件描述符。
  • 返回值:

    • 成功:0,失败:返回-1。

服务器端通信流程 

1.创建套接字: 使用 socket 函数创建一个套接字,指定协议族(通常是 AF_INET 表示IPv4)、套接字类型(SOCK_STREAM 表示TCP流套接字)、协议(通常为0,表示自动选择协议)。

int server_socket = socket(AF_INET, SOCK_STREAM, 0);

2.绑定地址: 使用 bind 函数将套接字与特定的IP地址和端口号绑定。

struct sockaddr_in server_address;
server_address.sin_family = AF_INET;
server_address.sin_port = htons(8888);
server_address.sin_addr.s_addr = INADDR_ANY;

bind(server_socket, (struct sockaddr *)&server_address, sizeof(server_address));

3.监听连接请求: 使用 listen 函数开始监听连接请求。

listen(server_socket, 5);  // 允许最多5个连接请求排队

4.接受连接: 使用 accept 函数接受客户端的连接请求,该函数会阻塞程序直到有客户端连接进来。

int client_socket = accept(server_socket, NULL, NULL);

5.进行数据交互: 使用 sendrecv 函数进行数据的发送和接收。

char buffer[1024];
recv(client_socket, buffer, sizeof(buffer), 0);
send(client_socket, "Hello from server", strlen("Hello from server"), 0);

6.关闭套接字: 使用 close 函数关闭服务端的套接字。

close(server_socket);

示例代码

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <arpa/inet.h>

int main()
{
    // 1.创建监听的套接字
    int fd = socket(AF_INET, SOCK_STREAM, 0);
    if (fd == -1)
    {
        perror("socket");
        return -1;
    }

    // 2.绑定本地的IP port
    struct sockaddr_in saddr;
    saddr.sin_family = AF_INET;
    saddr.sin_port = htons(9999);
    saddr.sin_addr.s_addr = INADDR_ANY; // INADD_ANY自动读取本地的ip地址
    int ret = bind(fd, (struct sockaddr *)&saddr, sizeof(saddr));
    if (ret == -1)
    {
        perror("bind");
        return -1;
    }

    // 3.设置监听
    ret = listen(fd, 128);
    if (ret == -1)
    {
        perror("listen");
        return -1;
    }

    // 4.阻塞并等待客户端的连接
    struct sockaddr_in caddr;
    int addrlen = sizeof(caddr);
    int cfd = accept(fd, (struct sockaddr *)&caddr, &addrlen);
    if (cfd == -1)
    {
        perror("accept");
        return -1;
    }

    // 连接建立成功,打印客户端的ip和端口信息
    char ip[32];
    printf("客户端的ip:%s,端口:%d\n", inet_ntop(AF_INET, &caddr.sin_addr.s_addr, ip, sizeof(ip)), ntohs(caddr.sin_port));

    // 5.通信
    while (1)
    { // 接受数据
        char buff[1024];
        int len = recv(cfd, buff, sizeof(buff), 0);
        if (len > 0)
        {
            printf("client say:%s\n", buff);
            send(cfd, buff, len, 0);
        }
        else if (len == 0)
        {
            printf("客户端已经断开了连接...\n");
            break;
        }
        else
        {
            perror("recv");
            break;
        }
    }
    
    close(fd);
    return 0;
}

客户端通信流程

1.创建套接字: 使用 socket 函数创建一个套接字。

int client_socket = socket(AF_INET, SOCK_STREAM, 0);

2.设置服务器地址: 设置服务器的地址信息,包括协议族、IP地址和端口号。

struct sockaddr_in server_address;
server_address.sin_family = AF_INET;
server_address.sin_port = htons(8888);
server_address.sin_addr.s_addr = inet_addr("127.0.0.1");

3.连接服务器: 使用 connect 函数连接到服务器。

connect(client_socket, (struct sockaddr *)&server_address, sizeof(server_address));

4.进行数据交互: 使用 sendrecv 函数进行数据的发送和接收。

char buffer[1024];
send(client_socket, "Hello from client", strlen("Hello from client"), 0);
recv(client_socket, buffer, sizeof(buffer), 0);

5.关闭套接字: 使用 close 函数关闭客户端的套接字。

close(client_socket);

代码示例

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <arpa/inet.h>

int main()
{
    // 1.创建通信的套接字
    int fd = socket(AF_INET, SOCK_STREAM, 0);
    if (fd == -1)
    {
        perror("socket");
        return -1;
    }

    // 2.连接服务器的IP port
    struct sockaddr_in saddr;
    saddr.sin_family = AF_INET;
    saddr.sin_port = htons(9999);
    inet_pton(AF_INET, "192.168.3.128", &saddr.sin_addr.s_addr);
    int ret = connect(fd, (struct sockaddr *)&saddr, sizeof(saddr));
    if (ret == -1)
    {
        perror("connect");
        return -1;
    }

    int number = 0;
    // 3.通信
    while (1)
    { // 发送数据
        char buff[1024];
        sprintf(buff, "你好,hello,world,%d...\n", number++);
        send(fd, buff, sizeof(buff), 0);

        // 接收数据
        memset(buff, 0, sizeof(buff));
        int len = recv(fd, buff, sizeof(buff), 0);
        if (len > 0)
        {
            printf("server say:%s\n", buff);
        }
        else if (len == 0)
        {
            printf("服务器端已经断开了连接...\n");
            break;
        }
        else
        {
            perror("recv");
            break;
        }
        sleep(1);
    }

    // 关闭文件描述符
    close(fd);

    return 0;
}

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

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

相关文章

单调栈与单调队列算法总结

单调栈 知识概览 单调栈最常见的应用是找到每一个数离它最近的且比它小的数。单调栈考虑的方式和双指针类似&#xff0c;都是先想一下暴力做法是什么&#xff0c;然后再挖掘一些性质如单调性&#xff0c;最终可以把目光集中在比较少的状态中&#xff0c;从而达到降低时间复杂…

【Linux】基础IO--重定向理解Linux下一切皆文件缓冲区

文章目录 一、重定向1.什么是重定向2.dup2 系统调用3.理解输入重定向、输出重定向和追加重定向4.简易shell完整实现 二、理解linux下一切皆文件三、缓冲区1.为什么要有缓冲区2.缓冲区的刷新策略3.缓冲区的位置4.实现一个简易的C语言缓冲区5.内核缓冲区 一、重定向 1.什么是重定…

VMware虚拟机系统CentOS镜像的下载

文章目录 阿里云下载官网下载参考文档 一些小版本可能过时或者其他原因已经不能存在了&#xff0c;只有大版本号最新的&#xff0c;或者其他最新版本 阿里云下载 1-百度搜索&#xff1a;阿里云 2-找到开发者社区 3-找到下载&#xff0c;选择镜像 4-选择系统 5-点击镜像地…

【eNSP实践】eNSP实战篇(2)之简单实现交换机与主机的配置(图文详解)

目录 写在前面涉及知识1、交换机实验1.1 实验条件1.2 实验步骤A、打开eNSP软件&#xff0c;创建拓扑B、搭建主机与交换机连线C、配置交换机和主机D、验证不同网段设备可通性 1.3 通过交换机查看MAC地址 写在最后 写在前面 其实前面文章我有介绍关于路由器的使用&#xff0c;但…

OCP Java17 SE Developers 复习题08

答案 答案 答案 A. This code is correct. Line 8 creates a lambda expression that checks whether the age is less than 5, making option A correct. Since there is only one parameter and it does not specify a type, the parentheses around the parameter are …

TrustZone​之在安全状态之间切换

如果处理器处于NS.EL1,而软件想要转移到S.EL1,应该如何实现呢? 要改变安全状态,无论是向上还是向下,执行都必须经过EL3,如下图所示: 前面的图表显示了在不同安全状态之间移动涉及的步骤的示例序列。逐步进行解释: 进入较高的异常级别需要一个异常。通常,此异常…

网络程序设计

互相连接&#xff0c;发送信息 tcp和udp协议 tcp会有准备&#xff0c;udp不会准备。 8080端口&#xff1a;tomcat端口&#xff0c;java和web相连接 80端口&#xff1a;http 21端口&#xff1a;ftp 套接字 socket&#xff1a;提供给程序可以对外进行连接的接口 ip地址 特…

利用github copilot完成代码,利用正则化完成字符串中信息查找

利用正则化完成字符串中的字符拆解。 下面的代码是实现在“计算机组成原理-计科2101-123456-小明同学.docx”中提取出班级&#xff08;grade&#xff09;&#xff0c;学号&#xff08;id&#xff09;&#xff0c;姓名&#xff08;name&#xff09;。以下的代码都是github copi…

java中Random随机数使用和生成随机数的多个示例

在 Java 中&#xff0c;我们可以使用 java.util.Random 类生成伪随机数。伪随机数的特性是&#xff0c;虽然它们看起来是随机的&#xff0c;但实际上它们是由一个固定的算法生成的。只要我们提供相同的种子&#xff0c;这个算法就会生成相同的数字序列。 首先&#xff0c;我们…

Java链接数据库

本文介绍的是Java链接数据库中的JDBC操作&#xff0c;JDBC虽然现在用的不多&#xff0c;但面试的时候会问道。需要有相应的了解。下面以链接MySQL为例子。 JDBC 什么jdbc Java DataBase Connectivity是一种用于执行SQL语句的Java API&#xff0c;它由一组用Java语言编写的类和…

pod容器内无法访问集群外部主机ipv6地址

一、背景 同事反馈他这边有一环境出现pod容器内无法请求集群外部主机ipv6地址&#xff0c;但是在pod所在集群所主机上是可以请求到外部主机ipv6地址。 二、问题处理过程 首先主机和主机之间ipv6地址能通讯&#xff0c;说明主机之间网络是没啥问题&#xff0c;哪问题就出在容器…

Python语言基础学习大纲(由某大模型生成)

自从上次经丙察察游了一次滇藏线&#xff0c;已有3个没写一篇了。今天利用由某大模型生成的上面这张思维导图&#xff0c;配合这个大模型生成的6000多字拼凑出一篇博文聊以交差。 Python语言概述 一、语言特点 1.语法简单明了 Python的语法简洁易懂&#xff0c;使得编写代码…

邮件群发工具的功能:实用性与高效率功能推荐

市场营销对于每个企业来讲都至关重要&#xff0c;他能为企业带来商机的增长&#xff0c;获得持续的收益。邮件营销作为一种传统但是较少为众多行业使用的营销手段&#xff0c;同样也存在着无限的潜力。 它可以实现&#xff1a; 精准点对点个性化营销。数据报表追踪营销效果。…

如果不小心修改了按钮的名字并且忘记了原名字

出现上述情况&#xff0c;可以右边点击转到代码&#xff0c;注释掉问题行&#xff0c;此页的设计界面就恢复了。

Taro 学习教程 - - - - - 开发环境的安装 helloworld

一、Taro脚手架安装 npm install tarojs/cli -g // or yarn add tarojs/cli -g // or cnpm install tarojs/cli -g1.1 如何判断taro安装成功 taro -v正常安装成功之后显示如图&#xff1a; 1.2 环境变量配置(自行判断是否需要手动配置) 如果遇到如下问题&#xff0c;则是需要…

顶级资源!五个免费图标素材网站

图片太花哨了&#xff0c;纯文本太单调了&#xff1f;别忘了设计师的魔法武器——图标&#xff01;图标材料是UI设计师不可缺少的一部分。优秀的图标设计不仅可以提高界面美感&#xff0c;还可以提高用户的互动体验&#xff0c;帮助用户更好地了解应用程序的功能和信息。在本文…

2024年CSC国际区域问题研究及外语高层次人才培养项目介绍

国家留学基金委&#xff08;CSC&#xff09;公布了2024年国际区域问题研究及外语高层次人才培养项目&#xff0c;申报时间均为3月中下旬。为帮助关注者了解项目申报情况&#xff0c;知识人网小编特整理本文。 近日&#xff0c;国家留学基金委&#xff08;CSC&#xff09;公布了…

P4715 【深基16.例1】淘汰赛-仅思路

首先从题干要求入手&#xff0c;我们可以了解到题目要求是二进一&#xff0c;不难想到这是二叉树的题 再来&#xff0c;从题干可以知道&#xff0c;我们所采用的结构体除了需要有树的两个左右节点指针外&#xff0c;还需要两个变量用来储存“能力值”和“编号” 在这道题中&am…

回归预测 | MATLAB实现CNN-BiLSTM(卷积双向长短期记忆神经网络

效果一览 基本介绍 提出一种同时考虑时间与空间因素的卷积&#xff0d;双向长短期记忆&#xff08; CNN-BiLSTM&#xff09;模型&#xff0c;将具有空间局部特征提取能力的卷积神经网络&#xff08;CNN&#xff09;和具有能同时考虑前后方向长时间信息的双向长短期记忆&#xf…

BL121EN:IEC 61850到OPC UA的即插即用无缝转换解决方案

添加图片注释&#xff0c;不超过 140 字&#xff08;可选&#xff09; 在当今快速发展的工业自动化领域&#xff0c;实现不同通信协议之间的无缝连接是提高系统集成度、数据共享和设备互操作性的关键。钡铼技术&#xff08;Bay-Tech&#xff09;BL121EN硬网关应运而生&#xf…