C语言实现TCP通信

2023-05-16

C语言通过socket编程实现TCP通信

服务端客户端通信例子:socket tcp 通信1,socket tcp通信2,udp使用讲解,socket udp通信例子

  1. TCP/IP协议

叫做传输控制/网际协议,又叫网络通信协议。实际上,它包含上百个功能的协议,如ICMP(互联网控制信息协议)、FTP(文件传输协议)、UDP(用户数据包协议)、ARP(地址解析协议)等。TCP负责发现传输的问题,一旦有问题就会发出重传信号,直到所有数据安全正确的传输到目的地。

2.套接字(socket):

在网络中用来描述计算机中不同程序与其他计算机程序的通信方式。socket其实是一种特殊的IO接口,也是一种文件描述符。

套接字分为三类:

流式socket(SOCK_STREAM):流式套接字提供可靠、面向连接的通信流;它使用TCP协议,从而保证了数据传输的正确性和顺序性。

数据报socket(SOCK_DGRAM):数据报套接字定义了一种无连接的服务,数据通过相互独立的保温进行传输,是无序的,并且不保证是可靠、无差错的。它使用的数据报协议是UDP。

原始socket:原始套接字允许对底层协议如IP或ICMP进行直接访问,它功能强大但使用复杂,主要用于一些协议的开发。

套接字由三个参数构成:IP地址,端口号,传输层协议。这三个参数用以区分不同应用程序进程间的网络通信与连接。

套接字的数据结构:C语言进行套接字编程时,常会使用到sockaddr数据类型和sockaddr_in数据类型,用于保存套接字信息。

两种结构体分别表示如下:

struct sockaddr
{
 
//地址族,2字节
unsigned short sa_family;
 
//存放地址和端口,14字节
char sa_data[14];
 
}
 
 
struct sockaddr_in
{
 
//地址族
short int sin_family;
 
//端口号(使用网络字节序)
unsigned short int sin_port;
 
//地址
struct in_addr sin_addr;
 
//8字节数组,全为0,该字节数组的作用只是为了让两种数据结构大小相同而保留的空字节
unsigned char sin_zero[8]
 
}

对于sockaddr,大部分的情况下只是用于bind,connect,recvfrom,sendto等函数的参数,指明地址信息,在一般编程中,并不对此结构体直接操作。而用sockaddr_in来替。

两种数据结构中,地址族都占2个字节,

常见的地址族有:AF_INET,AF_INET6AF_LOCAL。

这里要注意字节序的问题,最好使用以下函数来对端口和地址进行处理:

  1. uint16_t htons(uint16_t host16bit) 把16位值从主机字节序转到网络字节序

    uint32_t htonl(uint32_t host32bit) 把32位值从主机字节序转到网络字节序

  2. uint16_t ntohs(uint16_t net16bit) 把16位值从网络字节序转到主机字节序

    uint32_t ntohs(uint32_t net32bit) 把32位值从网络字节序转到主机字节序

使用socket进行TCP通信时,经常使用的函数有:

3.下面给出server和client的两个例子

更详细的例子

服务端:

/socket tcp服务器端/

#include <sys/stat.h>
 
#include <fcntl.h>
 
#include <errno.h>
 
#include <netdb.h>
 
#include <sys/types.h>
 
#include <sys/socket.h>
 
#include <netinet/in.h>
 
#include <arpa/inet.h>
 
#include <stdio.h>
 
#include <string.h>
 
#include <stdlib.h>
 
#include <unistd.h>
 
#define SERVER_PORT 6666
 
/*
监听后,一直处于accept阻塞状态,
直到有客户端连接,
当客户端如数quit后,断开与客户端的连接
*/
 
int main()
 
{
 
//调用socket函数返回的文件描述符
 
int serverSocket;
 
//声明两个套接字sockaddr_in结构体变量,分别表示客户端和服务器
 
struct sockaddr_in server_addr;
 
struct sockaddr_in clientAddr;
 
int addr_len = sizeof(clientAddr);
 
int client;
 
char buffer[200];
 
int iDataNum;
 
//socket函数,失败返回-1
 
//int socket(int domain, int type, int protocol);
 
//第一个参数表示使用的地址类型,一般都是ipv4,AF_INET
 
//第二个参数表示套接字类型:tcp:面向连接的稳定数据传输SOCK_STREAM
 
//第三个参数设置为0
 
if((serverSocket = socket(AF_INET, SOCK_STREAM, 0)) < 0)
 
{
 
perror("socket");
 
return 1;
 
}
 
bzero(&server_addr, sizeof(server_addr));
 
//初始化服务器端的套接字,并用htons和htonl将端口和地址转成网络字节序
 
server_addr.sin_family = AF_INET;
 
server_addr.sin_port = htons(SERVER_PORT);
 
//ip可是是本服务器的ip,也可以用宏INADDR_ANY代替,代表0.0.0.0,表明所有地址
 
server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
 
//对于bind,accept之类的函数,里面套接字参数都是需要强制转换成(struct sockaddr *)
 
//bind三个参数:服务器端的套接字的文件描述符,
 
if(bind(serverSocket, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0)
 
{
 
perror("connect");
 
return 1;
 
}
 
//设置服务器上的socket为监听状态
 
if(listen(serverSocket, 5) < 0)
 
{
 
perror("listen");
 
return 1;
 
}
 
while(1)
 
{
 
printf("监听端口: %d\n", SERVER_PORT);
 
//调用accept函数后,会进入阻塞状态
 
//accept返回一个套接字的文件描述符,这样服务器端便有两个套接字的文件描述符,
 
//serverSocket和client。
 
//serverSocket仍然继续在监听状态,client则负责接收和发送数据
 
//clientAddr是一个传出参数,accept返回时,传出客户端的地址和端口号
 
//addr_len是一个传入-传出参数,传入的是调用者提供的缓冲区的clientAddr的长度,以避免缓冲区溢出。
 
//传出的是客户端地址结构体的实际长度。
 
//出错返回-1
 
client = accept(serverSocket, (struct sockaddr*)&clientAddr, (socklen_t*)&addr_len);
 
if(client < 0)
 
{
 
perror("accept");
 
continue;
 
}
 
printf("等待消息...\n");
 
//inet_ntoa ip地址转换函数,将网络字节序IP转换为点分十进制IP
 
//表达式:char *inet_ntoa (struct in_addr);
 
printf("IP is %s\n", inet_ntoa(clientAddr.sin_addr));
 
printf("Port is %d\n", htons(clientAddr.sin_port));
 
while(1)
 
{
 
printf("读取消息:");
 
buffer[0] = '\0';
 
iDataNum = recv(client, buffer, 1024, 0);
 
if(iDataNum < 0)
 
{
 
perror("recv null");
 
continue;
 
}
 
buffer[iDataNum] = '\0';
 
if(strcmp(buffer, "quit") == 0)
 
break;
 
printf("%s\n", buffer);
 
 
 
printf("发送消息:");
 
scanf("%s", buffer);
 
printf("\n");
 
send(client, buffer, strlen(buffer), 0);
 
if(strcmp(buffer, "quit") == 0)
 
break;
 
}
 
}
 
close(serverSocket);
 
return 0;
 
}

客户端:

/socket tcp客户端/

#include <sys/stat.h>
 
#include <fcntl.h>
 
#include <errno.h>
 
#include <netdb.h>
 
#include <sys/types.h>
 
#include <sys/socket.h>
 
#include <netinet/in.h>
 
#include <arpa/inet.h>
 
#include <stdio.h>
 
#include <string.h>
 
#include <stdlib.h>
 
#include <unistd.h>
 
#define SERVER_PORT 6666
 
/*
连接到服务器后,会不停循环,等待输入,
输入quit后,断开与服务器的连接
*/
 
int main()
 
{
 
//客户端只需要一个套接字文件描述符,用于和服务器通信
 
int clientSocket;
 
//描述服务器的socket
 
struct sockaddr_in serverAddr;
 
char sendbuf[200];
 
char recvbuf[200];
 
int iDataNum;
 
if((clientSocket = socket(AF_INET, SOCK_STREAM, 0)) < 0)
 
{
 
perror("socket");
 
return 1;
 
}
 
serverAddr.sin_family = AF_INET;
 
serverAddr.sin_port = htons(SERVER_PORT);
 
//指定服务器端的ip,本地测试:127.0.0.1
 
//inet_addr()函数,将点分十进制IP转换成网络字节序IP
 
serverAddr.sin_addr.s_addr = inet_addr("127.0.0.1");
 
if(connect(clientSocket, (struct sockaddr *)&serverAddr, sizeof(serverAddr)) < 0)
 
{
 
perror("connect");
 
return 1;
 
}
 
printf("连接到主机...\n");
 
while(1)
 
{
 
printf("发送消息:");
 
scanf("%s", sendbuf);
 
printf("\n");
 
send(clientSocket, sendbuf, strlen(sendbuf), 0);
 
 
 
if(strcmp(sendbuf, "quit") == 0)
 
break;
 
printf("读取消息:");
 
recvbuf[0] = '\0';
 
iDataNum = recv(clientSocket, recvbuf, 200, 0);
 
recvbuf[iDataNum] = '\0';
 
printf("%s\n", recvbuf);
 
}
 
close(clientSocket);
 
return 0;
 
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

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

  • 关闭子进程中打开的套接字

    我有一个 SIP 服务器 守护进程 它正在侦听 tcp 套接字 5060 现在 在这个父进程中 我创建一个子进程并在子进程中执行一些操作 现在 当我在父进程中关闭此 tcp 套接字并尝试再次创建 假设我在此服务器上禁用和启用 SIP 时 会
  • 在没有源的情况下更改 .jar 文件?

    我有一个基于 Java 的 TCP 客户端 它与我们的生产服务器通信 我正在重写它 客户端对服务器的 IP 和端口进行硬编码 我想要做的就是将客户端中的 IP 地址更改为 127 0 0 1 我可以在我的开发盒上使用相同的端口号 问题是 我
  • http.sys 究竟是如何工作的[关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 我正在尝试更深入地了解 IIS 的工作原理 我理解 http sys 是它的主要组件之一 然而 我一直很难找到有关它的易于理解的信息
  • WebSockets ping/pong,为什么不 TCP keepalive?

    WebSockets有选择权 https www rfc editor org rfc rfc6455 section 5 5 2发送 ping 到另一端 另一端应该用 pong 响应 收到 Ping 帧后 端点必须发送 Pong 帧 响应
  • 如何在.NET中创建HTTP请求侦听器Windows服务

    我想创建充当 HTTP 侦听器并可以处理大约 500 个客户端的 Windows 服务 这种服务有什么特别的考虑吗 我对 HTTPListener 类和 TCPListener 类有点困惑 将哪一个用于 Windows 服务将 接受客户端连
  • 套接字术语 - “阻塞”是什么意思?

    当谈论 C 中的套接字编程时 术语 阻塞 是什么意思 我需要构建一个服务器组件 可能是 Windows 服务 来接收数据 进行一些处理并将数据返回给调用者 呼叫者可以等待回复 但我需要确保多个客户端可以同时呼叫 如果客户端 1 连接并且我花
  • 不调用bind()的情况下监听()

    我尝试了以下方法 int sockfd socket listen sockfd 10 accept sockfd 没有一个调用失败 并且程序开始阻塞 就像我调用了bind 一样 在这种情况下会发生什么 由于没有本地地址或端口 是否永远无法
  • TCP 数据偶尔会以错误的顺序接收且不完整

    我用 Java 创建了 TCP 服务器应用程序 并用 C 创建了客户端应用程序 当我发送数据时 客户端有时会乱序接收数据 有时部分会完全丢失 基本上 我在服务器 java 中使用的代码如下 已删除 ServerSocket welcomeS
  • WCF TCP 客户端 - 如何使用它们的基本指南?

    我有一个 WCF 服务并希望使用 TCP 绑定连接到它 这一切都很好 但是你应该如何处理客户呢 我注意到 如果您为每个调用创建一个新客户端 它不会重新使用该通道 并会留下一堆 TCP 连接 直到超时 创建客户端 调用其方法 然后关闭它是正常
  • C# 服务器和 Java 客户端:TCP 套接字通信问题

    我用 C 编写了一个服务器程序TCPListner和一个使用套接字的 Java 客户端程序 但我无法将复杂的对象从 Java 客户端发送到 C 服务器 当我通过将字符串转换为字节数组从 Java 客户端发送到 C 服务器时 当转换回字符串时
  • TCP 服务器的 GCP 计算引擎防火墙规则

    我创建了一个具有静态外部 IP 地址的 GCP 计算引擎实例 机器类型 n1 standard 2 2 个 vCPU 7 5 GB 内存 操作系统是Linux Debian 我的目的是在机器上创建一个普通的 Node js TCP 服务器
  • 如何监控 TCP 连接的 cwnd 和 ssthresh 值? [关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 我希望在通过套接字连接发送或接收数据包时确定这些值 有没有现有的工具可以做到这一点 The ss http linux die net m
  • 如何识别用户空间和内核空间之间的特定套接字?

    我在用户空间中有一个库 可以拦截套接字层调用 例如socket connect accept 等等 我只处理 TCP 套接字 在内核空间中 我有一个网络内核模块 它处理所有 TCP 连接 我需要能够在驱动程序中识别哪些套接字被用户空间库拦截
  • wireshark 和 tcpdump -r:奇怪的 tcp 窗口大小

    我正在使用 tcpdump 捕获 http 流量 并且对 TCP 慢启动以及窗口大小如何增加感兴趣 sudo tcpdump i eth1 w wget tcpdump tcp and port 80 当我使用 Wireshark 查看转储
  • TCP 代理:在后端不可用时保持连接

    在 Docker 设置的上下文中 我想使用类似大使的模式来允许某些容器 例如数据库服务器 正常重新启动 而不必重新启动所有依赖的容器 例如 Web 服务器 并且没有错误消息 因为 数据库服务器不可用 因此 我想知道 是否有一个 TCP 代理
  • Android TCP 连接最佳实践

    我正在开发一个需要 TCP 连接到 TCP 服务器的 Android 应用程序 用 Node js 编写 我的 Android TCP 客户端正在工作 可以来回发送消息 我的具体问题是 在 Android 中处理与服务器的 TCP 连接的最
  • 如何模拟客户端和服务器之间的套接字断开连接(在 Windows 上)?

    我已经实现了一种 心跳解决方案 我想看看在实际情况下网络 故障 时会发生什么 特别是当套接字上没有流量时发生这种情况 问题 我只有一台电脑 我在windows java上 我想简单地拔掉网线 停用网卡不会影响这两个进程 因为它们在同一个盒子
  • Linux环境下串口数据转换为TCP/IP

    我需要从Linux系统的串口获取数据并将其转换为TCP IP发送到服务器 这很难做到吗 我有一些基本的编程经验 但对 Linux 的经验不多 有没有开源应用程序可以做到这一点 在 Linux 中您不需要编写程序来执行此操作 只是pipe h
  • 构建多线程 TCP/IP 服务器

    我想构建一个可供最多 100 个并发客户端使用的 TCP IP 服务器 但仍不确定如何开始 至少我需要服务器 监听客户端 并将它们全部存储在数组或列表中 对于每个客户端 它需要根据其客户端状态接收和发送数据 当有人连接或断开连接时 服务器应
  • Python套接字模块:Recv()数据响应被切断

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

随机推荐

  • 拉流推流服务器设计

    背景 该服务器也是基于一个客户的需求产生的 客户那边使用的是腾讯的直播sdk xff0c 将不同终端的流推到腾讯云平台 xff0c 但是又想推到其他平台 xff0c 基于此需求 xff0c 该产品产生了 该产品通讯协议使用的是WebSock
  • 开发实现C++ RTMP直播推流sdk

    前言 rtmp即Real Time Messaging Protocol xff08 实时消息传输协议 xff09 的首字母缩写 xff0c 它是由Adobe公司提出的一种应用层的协议 xff0c 用来解决多媒体数据传输流的多路复用 xff
  • 开发实现C++ RTMP直播拉流播放器

    背景 该直播播放器的背景是来源于 拉流推流服务器设计 的一个分支 xff0c 它的重点是把拉下来的流进行解码显示播放 设计点 要实现跨平台 xff0c 目前支持的平台linux和windows要模块化和结构化可以拉各个平台的直播流要音视频同
  • 校验和计算原理

    校验和思路 首先 xff0c IP ICMP UDP和TCP报文头都有检验和字段 xff0c 大小都是16bit xff0c 算法基本上也是一样的 在发送数据时 xff0c 为了计算数据包的检验和 应该按如下步骤 xff1a 1 把校验和字
  • gb 28181的20位编码简介

    图解Python数据结构与算法 实战篇 举例 xff1a 36030000042000000003 设备的20位编码组成 国标编码由中心编码 xff08 8位 xff09 行业编码 xff08 2位 xff09 类型编码 xff08 3位
  • 继承的构造析构函数&&父类子类同名函数,变量的调用

    include lt iostream gt include 34 string 34 using namespace std class Base public int m A int m B 61 20 Base m A 61 100
  • CMake 之静态库依赖动态库,如何使用该静态库

    参考 xff1a xff08 参考文章用的Makefile 我自己用的CMake xff09 静态库链接动态库时 xff0c 如何使用该静态库 newchenxf的专栏 CSDN博客 链接静态库 1 先建立如下工程目录文件 下载 xff08
  • 单片机堆栈小知识

    目录 一 关于单片机堆栈的基础知识 1 STM32程序数据分类 2 STM32内存 RAM 分配 3 经典例子分析 xff1a 4 STM32堆栈位置 5 STM32栈增长方式 三 如何设置STM32的堆栈大小 1 MDK编译环境下 2 I
  • 要点初见:用Python进行微观交通模型仿真——基于SUMO的伯克利开源项目Flow Project初探与拓展

    后续拓展 xff1a 要点初见 xff1a 安装教程与二度拓展 基于SUMO的Flow Project xff08 附代码链接 xff09 通俗来讲 xff0c 微观交通模型仿真就是从车辆个体的视角 xff08 看动画 xff09 进行交通
  • 要点初见:安装教程与二度拓展——基于SUMO的Flow Project(附代码链接)

    前文链接 xff1a 要点初见 xff1a 用Python进行微观交通模型仿真 基于SUMO的伯克利开源项目Flow Project初探与拓展 前文链接中是博主先前写TRB论文时根据个人研究所写的Flow Project介绍 代码解释以及初
  • 要点初见:开源AI绘画工具Stable Diffusion代码分析(文本转图像)、论文介绍(上)

    博主先前整理并简单介绍了AI绘图工具的部署资源与攻略 xff0c 觉得其中Stable Diffusion部分不够带劲 xff0c 故开始试图从论文与代码中一探究竟 前文链接如下 xff1a 要点初见 xff1a AI绘图工具的部署资源 攻
  • 要点初见:开源AI绘画工具Stable Diffusion代码分析(文本转图像)、论文介绍(下)

    前文链接如下 xff1a 要点初见 xff1a 开源AI绘画工具Stable Diffusion代码分析 xff08 文本转图像 xff09 论文介绍 xff08 上 xff09 BingLiHanShuang的博客 CSDN博客 二 St
  • 要点初见:Stable Diffusion NovelAI模型优质文字Tag汇总与实践【魔咒汇总】

    目前贴吧 B站上有大量Stable Diffusion的模型资源 TAG TAG生成器分享 xff0c 其中居然有不少试图靠信息差把这些开源资源卖钱的 加上目前网上相关的TAG整理贴极少 xff0c 不少TAG也是以图片的形式存在 xff0
  • UART详解

    UART 通用异步收发传输器 xff08 Universal Asynchronous Receiver Transmitter xff0c 通常称作UART xff09 是一种串行异步收发协议 xff0c 应用十分广泛 UART工作原理是
  • Python订阅自定义ROS topic并读取message

    背景 最近部署了基于ROS的实时稠密场景建图 参考Elastic bridge 现在需要用python获取相机每一时刻的pose 该pose的消息类型定义在FrameState msg 文件中 具体内容如下 uint64 seq uint6
  • 要点初见:双硬盘下的Win10+Ubuntu16.04双系统安装

    按照网上博客的安装教程安装的Win10 43 Ubuntu16 04双系统安装了好几遍都不成功 xff1f 启动Ubuntu左上一直有个光标在闪 xff1f 如果你的电脑也是双硬盘 xff08 装Windows系统的固态硬盘 43 机械硬盘
  • 要点初见:OpenCV3中ORB特征提取算法的实现与分析

    ORB特征提取算法是一种通过检测提取待测图片与模板图片中的灰度特征 xff0c 实现模板图片与待测图片匹配的一种特征提取算法 相比于模板匹配matchTemple xff0c ORB更集中于图像的灰度细节 xff0c 速度也更快 ORB的全
  • 为什么模板函数应该定义在头文件内

    为什么模板函数应该定义在头文件内 tang05505622334的博客 CSDN博客 头文件 模板函数 参考 xff1a https www cnblogs com cnsec p 3789824 htmlgeneral的编译链接过程 xf
  • Cartographer详解

    Cartographer 论文解读 一 Introduction 在建图上应用SLAM并不是一个新的概念 xff0c 这里不再作为本文的重点 本文的贡献在于 xff1a 提出了一种新的基于激光数据的回环检测方法 xff0c 这种方法可以减少
  • C语言实现TCP通信

    C语言通过socket编程实现TCP通信 服务端客户端通信例子 xff1a socket tcp 通信1 xff0c socket tcp通信2 xff0c udp使用讲解 xff0c socket udp通信例子 TCP IP协议 叫做传