C语言实现TCP通信

2023-05-16

如果想要自己写一个服务器和客户端,我们需要掌握一定的网络编程技术,个人认为,网络编程中最关键的就是这个东西——socket(套接字)。socket(套接字):简单来讲,socket就是用于描述IP地址和端口,是一个通信链的句柄,可以用来实现不同虚拟机或不同计算机之间的通信。

TCP协议

TCP协议:是一种面向连接的、可靠的、基于字节流的传输层通信协议,由IETF的RFC 793定义。在简化的计算机网络OSI模型中,它完成第四层传输层所指定的功能。

关键词:三次握手,可靠,基于字节流。

可能有朋友会问,TCP就这么简单一句话吗?当然不是,TCP作为非常重要的传输协议,细节知识是很多的,细讲起来这一篇文章怕是不够。不过在本篇内容中,我们只需了解他的几个关键词特性,就能很好的理解下面的内容。

C语言实现TCP通信C语言实现TCP通信

TCP服务器端和客户端的运行流程

如图,这是一个完整的TCP服务器——客户端的运行流程图,其实我个人认为程序啊,不管哪个语言都是一样,核心就在于算法的设计和函数的调用。那么图中的函数都是什么意思呢?

1.创建socket

socket是一个结构体,被创建在内核中


sockfd=socket(AF_INET,SOCK_STREAM,0); //AF_INT:ipv4, SOCK_STREAM:tcp协议  

2.调用bind函数

将socket和地址(包括ip、port)绑定。

需要定义一个结构体地址,以便于将port的主机字节序转化成网络字节序


struct sockaddr_in myaddr; //地址结构体 
  

bind函数


bind(sockfd,(struct sockaddr*)&myaddr,sizeof(serveraddr))
  

3.listen监听,将接收到的客户端连接放入队列


listen(sockfd,8) //第二个参数是队列长度
  

4.调用accept函数,从队列获取请求,返回socket描 述符

如果无请求,将会阻塞,直到获得连接


int fd=accept(sockfd, NULL,NULL);//这边采用默认参数
  

5.调用read/write进行双向通信

6.关闭accept返回的socket


close(scokfd); 
  

下面放出完整代码


/*服务器*/ 
#include  
#include  
#include  
#include  
#include <sys/types.h> 
#include <sys/socket.h> 
#include <arpa/inet.h> 
#include <netinet/in.h> 
int main() 
{ 
    int sockfd = socket(AF_INET, SOCK_STREAM, 0);//创建套接字 
    if (sockfd < 0) { perror("socket"); return -1; } //创建失败的错误处理 printf("socket..............\n"); //成功则打印“socket。。。。” struct sockaddr_in myaddr; //创建“我的地址”结构体 memset(&myaddr, 0, sizeof(myaddr)); //对内存清零(保险起见) myaddr.sin_family = AF_INET; //选择IPV4地址类型 myaddr.sin_port = htons(8888); //选择端口号 myaddr.sin_addr.s_addr = inet_addr("192.168.3.169"); //选择IP地址 if (0 > bind(sockfd, (struct sockaddr*)&myaddr, sizeof(myaddr)))//绑定套接字 
    { 
        perror("bind"); 
        return -1; 
    } 
    printf("bind..........\n"); 
  
    if (0 > listen(sockfd, 8))//调用listen对指定端口进行监听 
    { 
        perror("listen"); 
        return -1; 
    } 
    printf("listen............\n"); 
     
    int connfd = accept(sockfd, NULL, NULL);//使用accept从消息队列中获取请求 
    if (connfd < 0) { perror("accept"); return -1; } printf("accept..............\n"); char buf[100];//定义一个数组用来存储接收到的数据 int ret; while (1) { memset(buf, 0, sizeof(buf)); ret = read(connfd, buf, sizeof(buf)); if (0 > ret) 
        { 
            perror("read"); 
            break; 
        }//执行while循环读取数据,当 
        else if (0 == ret) 
        { 
            printf("write close!\n"); 
            break; 
        } 
        printf("recv: "); 
        fputs(buf, stdout);//打印接收到的数据 
    } 
    close(sockfd);//关闭套接字 
    close(connfd);//断开连接 
    return 0; 
} 
/*客户端*/(具体功能和服务器一样,所以不再加注释) 
#include  
#include  
#include  
#include  
#include <sys/types.h> 
#include <sys/socket.h> 
#include <netinet/in.h> 
#include <arpa/inet.h> 
int main() 
{ 
 int sockfd; 
    if (0 > (sockfd = socket(AF_INET, SOCK_STREAM, 0))) 
    { 
        perror("socket"); 
        return -1; 
    } 
    printf("socket...........\n"); 
     
    struct sockaddr_in srv_addr; 
    memset(&srv_addr, 0, sizeof(srv_addr)); 
    srv_addr.sin_family         = AF_INET; 
    srv_addr.sin_port           = htons(8888); 
    srv_addr.sin_addr.s_addr    = inet_addr("192.168.3.169"); 
    if (0 > connect(sockfd, (struct sockaddr*)&srv_addr, sizeof(srv_addr))) 
    { 
        perror("connect"); 
        return -1; //exit //pthread_exit 
    } 
    printf("connect..............\n"); 
    char buf[100]; 
    int ret; 
    while (1) 
    { 
        printf("send: "); 
        fgets(buf, sizeof(buf), stdin); 
        ret = write(sockfd, buf, sizeof(buf)); 
        if (ret < 0) 
        { 
            perror("write"); 
            break; 
        } 
        if (strncmp(buf, "quit", 4) == 0) 
            break; 
    } 
    close(sockfd); 
    return 0; 
}   

干货:《Linux就该这么学》

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

C语言实现TCP通信 的相关文章

  • 为什么我无法发送这个IP数据包?

    我正在尝试使用 C 发送 IP 数据包 destAddress IPAddress Parse 192 168 0 198 destPort 80 Create a raw socket to send this packet rawSoc
  • 很难理解带有 async_read 和 async_write 的 Boost ASIO TCP 的一些概念

    我很难理解使用 async read 和 async write 时构建 tcp 客户端的正确方法 这examples http www boost org doc libs 1 38 0 doc html boost asio examp
  • 是什么导致 MSSQL 中出现“非阻塞套接字上的操作将阻塞”错误?

    错误 异常查询为 CREATE NONCLUSTERED INDEX I1 ON AllAccounts BAK Master received Day ASC 出现异常 发生一个或多个错误 错误 异常内部异常无法从传输连接读取数据 非阻塞
  • 如何使用 kotlin 通过 TCP 连接发送和接收字符串

    我在 Windows 上有一个 TCP 服务器 我想在服务器和我的 Android 设备之间发送和接收文本字符串 我花了很多时间搜索使用 Kotlin 的示例 但没有找到任何有用的代码 所以我现在只能创建套接字并连接 fun connect
  • Socket ReceiveAsync 合并数据包

    我打算通过套接字接收数据包 但由于它们是从发送方以高频率发送的 因此其中许多数据包被打包成一个byte array SocketAsyncEventArgs Buffer然后保存多个数据包 即使它们是单独发送的 使用验证wireshark
  • syn队列和accept队列的混淆

    在阅读TCP源码时 我发现一个困惑的事情 我知道 TCP 在 3 次握手中有两个队列 第一个队列存储服务器收到的连接SYN并发回ACK SYN 我们称之为同步队列 第二个队列存储3WHS成功并建立连接的连接 我们称之为接受队列 但在阅读代码
  • Scapy 不需要的 RST TCP 数据包

    为了理解TCP是如何工作的 我尝试伪造自己的TCP SYN SYN ACK ACK 基于教程 http www thice nl creating ack get packets with scapy http www thice nl c
  • 如何模拟客户端和服务器之间的套接字断开连接(在 Windows 上)?

    我已经实现了一种 心跳解决方案 我想看看在实际情况下网络 故障 时会发生什么 特别是当套接字上没有流量时发生这种情况 问题 我只有一台电脑 我在windows java上 我想简单地拔掉网线 停用网卡不会影响这两个进程 因为它们在同一个盒子
  • net.TCPConn 允许在 FIN 数据包后写入

    我正在尝试为一些服务器端代码编写单元测试 但我在确定关闭测试用例时遇到了困难 环回 TCP 连接似乎无法正确处理干净关闭 我在一个示例应用程序中重现了这一点 该应用程序按顺序执行以下操作 创建客户端和服务器连接 通过从客户端向服务器成功发送
  • Go TCP 读取是非阻塞的

    我正在尝试用 Go 创建服务器和客户端 我已经成功地与服务器和客户端进行通信 但我遇到的问题是golang中的TCP读取是非阻塞的 我想知道 golang 中的读取是否有可能像 C 中的读取一样阻塞 谢谢 EDIT 这是服务器的源代码 fu
  • 为什么我们可以将 sockaddr 转换为 sockaddr_in

    我明白为什么强制转换很有用sockaddr to sockaddr in 但我不明白这怎么可能 据我所知 它们的大小相同sockaddr in添加了sin zero使其大小相同 我想知道编译器如何知道从哪里获取信息sockaddr in如果
  • Python套接字模块:Recv()数据响应被切断

    解释 我目前正在尝试使用 python 脚本控制智能电源板 为了实现这一点 我使用了带有套接字模块的 TCP 连接 大约 75 的情况下 我会得到我正在寻找的响应 数据 并且一切都运行良好 然而 大约 25 的情况下 响应会以完全相同的长度
  • ZeroMQ可以用来接受传统的套接字请求吗?

    我正在尝试使用 ZeroMQ 重写我们的旧服务器之一 现在我有以下服务器设置 适用于 Zmq 请求 using var context ZmqContext Create using var server context CreateSoc
  • 简单的跨平台 TCP IP API?

    我不打算使用像 QT 或 wxWidgets 的 API 这样的大东西 我只想要可以在 Android iOS Windows Mac Linux 上运行的简单套接字 我正在制作一个事件驱动的纸牌游戏 所以 TCP 是最好的 本质上 我只想
  • 如何查找连接到 AF_INET 套接字的客户端的 UID?

    有什么方法或类似的东西ucred for AF UNIX如果是AF INET插座 TCP在我的例子中 找出连接到我的套接字的客户端的UID 还有 proc net tcp但它显示了UID of the creator插座的而不是连接的cli
  • 如何强制关闭 TcpListener

    我有一个通过 tcpListener 进行通信的服务 问题是当用户重新启动服务时 抛出 地址已在使用 异常 并且服务在几分钟左右无法启动 有没有办法告诉系统终止旧连接 以便我可以打开一个新连接 我不能只使用随机端口 因为服务无法通知客户端端
  • 当 TCP 序列号到达而不是预期时会发生什么情况?

    我正在编写一个程序 使用 libpcap 捕获数据包并重新组装 TCP 流 我的程序只是监视流量 因此我无法控制数据包的接收和发送 我的程序忽略所有非 TCP IP 流量 我根据 ISN 计算下一个预期序列号 然后计算连续的 SEQ 号 我
  • ADB TCPIP 连接问题

    我有两台 Galaxy S3 其中一个已扎根 另一个则未扎根 因此 当我尝试通过本地网络连接它们时 计算机可以看到已root的计算机 但是正常的就卡在tcpip这一步了 所以 我写 adb tcpip 5555 It says restar
  • 如何知道哪个本地应用程序连接到我的套接字(Windows)

    我有一个绑定到某个 TCP 端口的 Windows 服务 该端口用于我的应用程序之间的 IPC 有没有一种编程 WinAPI WinSocket 等 方法可以知道哪个应用程序连接到我的端口 即在我的 Windows 服务中 我想获取连接到我
  • 通过 TCP/.NET SSLStream 发送文件很慢/无法正常工作

    我正在编写一个与 SSL 配合使用的服务器 客户端应用程序 通过SSLStream 它必须做很多事情 不仅仅是文件接收 发送 目前 它的工作原理是 只有一个连接 我总是使用从客户端 服务器发送数据SSLStream WriteLine 并使

随机推荐

  • 我对onSizeChange方法的源码解析

    如果当前的自定义控件是继承ViewGroup xff0c 那么在ViewGroup重写的layout方法中 xff1a 可知调用父类也就是View的layout方法 再看View的layout方法 xff1a 查看设置自己坐标的setFra
  • 5 个你不知道的关于 Python 类的技巧

    5 个你不知道的关于 Python 类的技巧 1 创建 一个 常量值2 多个类构造函数3 创建枚举4 迭代器5 以列表的形式访问一个类 Python 有许多强大的特性 xff0c 在处理类时提供了极大的灵活性 在这里 xff0c 我将向您展
  • 激光雷达和RTK的标定(无人小车)

    总结一下最近的标定工作 xff0c 标定平台是实验室的无人小车 xff0c 目标是实现激光雷达 lidar 和RTK的标定 xff0c 也就是求解lidar到RTK的位姿变换矩阵 采用的代码是ETH的lidar align https gi
  • 虚拟机安装Ubuntu20.04 + VCS2018

    虚拟机安装Ubuntu20 04 43 VCS2018 前言正文1 准备内容Vmware Workstation 16 prounbuntu 20 04 安装包vcs 43 scl 43 verdi等安装包 2 Ubuntu系统的安装ope
  • input里面file实现上传图片及预览功能

    在这里插入简单的HTML代码片 lt form action 61 34 34 gt 文件 xff1a lt input type 61 34 file 34 name 61 34 myFile 34 id 61 34 myFile 34
  • 创建ROS-wrapper

    创建ROS wrapper 对高博的ygz stereo inertial的开源算法添加ROS node源文件的编写CMakeLists文件的编写分目录下的CMakeLists完整CMakeLists路径 home fei devv ygz
  • 新买了块翼联的AX200的网卡,结果开移动热点的时候遇到了点问题

    买网卡这事的起因要从入手了switch说起 xff0c 直连网不是不能用 xff0c 就是太难用了 xff0c 下载个东西要几十个小时 xff0c 玩个马造2连地图都下载不了 然后试用了3天的网易uu加速器 xff0c 好用是真的好用 xf
  • HDU 1085(Holding Bin-Laden Captive!)

    题意 xff1a 有三种价值分别为 1 2 5 的硬币 xff0c 每一种分别由 a b c 个 xff0c 求这些硬币不能组成的最小价值 分析 xff1a 生成函数板子题 xff08 贴一个讲生成函数的链接https blog csdn
  • 大电流的走线和过孔

    工程师在设计的时候 xff0c 很容易忽略走线宽度的问题 xff0c 因为在数字设计时 xff0c 走线宽度不在 考虑范围里面 通常情况下 xff0c 都会尝试用最小的线宽去设计走线 xff0c 这时 xff0c 在大电流时 xff0c 将
  • c++ 实现基本数据结构代码

    数据结构是计算机科学的一个重要的分支 xff0c 主要研究如何有效地存储和组织数据以便于快速访问和操作 常见的数据结构有 xff1a 数组 xff1a 是一种线性的数据结构 xff0c 可以通过索引来访问数组中的元素 链表 xff1a 是一
  • Jetson开发实战记录(二):Jetson Xavier NX版本区别以及烧录系统

    Jetson开发实战记录 xff08 二 xff09 xff1a Jetson Xavier NX版本区别以及烧录系统 一 Jetson Xavier NX类型1 SD卡槽的版本 xff08 官方版本 xff09 2 带eMMC存储芯片的版
  • ZYNQ7000(AX7020)移植Linux操作系统(二):u-boot的编译和启动

    总述 我们已经在 PC 上已经安装了 Ubuntu 客户操作系统 xff0c 以及在 Ubuntu 操作系统里安装了 SDK 2015 4 工具 要想在 Zynq 平台上运行 Ubuntu 操作系统 xff0c 必项预先制作作镜像文件 xf
  • 10个让你的 Python 代码更具 pythonic 风格的示例

    10个让你的 Python 代码更具 pythonic 风格的示例 1 变量交换 2 函数返回元组 xff08 自动打包 解包 xff09 3 多重比较 4 多重比较 5 列表推导式 6 将 Python 字典当做缓存 7 关键字参数 8
  • 进程的调度算法

    先来先服务调度算法 xff1a 先来先服务调度算法是一种最简单的调度算法 xff0c 也称为先进先出或严格排队方案 当每个进程就绪后 xff0c 它加入就绪队列 当前正运行的进程停止执行 xff0c 选择在就绪队列中存在时间最长的进程运行
  • 华为云服务器购买及使用指南

    前言 作者参与牛客网的买服务器返现活动 xff0c 以某个奇妙的价格价格购入了一个一年的华为云服务器 xff0c 具体多少钱就不透露了 xff0c 不然会被当作广告性能参数如下 xff1a 购买 偶然看到这个活动 xff0c 然后点进去 x
  • JS 简单的事件

    实现鼠标滑过按钮时显示文本 xff0c 滑出时隐藏文本 span class token doctype lt DOCTYPE html gt span span class token tag span class token tag s
  • 在ROS中实现darknet_ros(YOLO V3)检测以及训练自己的数据集

    目录 1 darknet ros介绍 2 darknet ros原始项目编译测试 3 yolov3训练自己的数据集 4 使用自己训练好的数据集 1 darknet ros介绍 Darknet概述 https blog csdn net u0
  • apache options index 设置问题

    禁止显示Apache目录列表 Indexes FollowSymLinks 如何修改目录的配置以禁止显示Apache 目录列表 缺省情况下如果你在浏览器输入地址 xff1a http localhost 8080 如果你的文件根目录里有in
  • Centos7.7安装vncserver虚拟网络控制台

    虚拟网络控制台 xff08 VNC xff09 是一个图形桌面共享软件 xff0c 允许您使用键盘和鼠标远程控制另一台计算机 系统环境 服务端 xff1a Centos7 7 Minimal客户端 xff1a Windows10客户端VNC
  • C语言实现TCP通信

    如果想要自己写一个服务器和客户端 xff0c 我们需要掌握一定的网络编程技术 xff0c 个人认为 xff0c 网络编程中最关键的就是这个东西 socket 套接字 socket 套接字 xff1a 简单来讲 xff0c socket就是用