C语言实现TCP编程

2023-05-16

C语言实现TCP编程

  • 1.主机字节序和网络字节序
  • 2.套接字的地址结构
    • IP地址转化的方法
  • 3. TCP的网络接口
  • 4. TCP服务器端的编程流程
  • 5. TCP客户端的编程流程
  • 6.运行结果

1.主机字节序和网络字节序

主机字节序: 不同的芯片,所采用的数值存储方式是不同:大端模式&小端模式
网络字节序: 统一使用大端模式来表示数据

2.字节序的转化
#include <netinet/in.h>
uint32_t ntohl (uint32_t __netlong); // 网络字节序转化为	主机字节序 long
uint16_t ntohs (uint16_t __netshort); // 网络字节序转化为主机字节序 short
uint32_t htonl (uint32_t __hostlong); // 主机字节序转化为网络字节序 long
uint16_t htons (uint16_t __hostshort); // 主机字节序转化	为网络字节序 short

2.套接字的地址结构

运行在两个不同主机上的进程想要通信: 必须知道 IP地址 端口号
// 通用的地址结构
struct sockaddr
{
sa_family_t sa_family;
char sa_data[14];
};
// IPV4 专有的地址结构
struct sockaddr_in
{
sa_family_t sin_family; // 地址簇 AF_INET
uint16_t sin_port; // 端口号: 将主机字节序转化为网络字节序 0--1024 系统预留 1025 -- 4096 知名端口号 4097 --
65535
struct in_addr sin_addr;
};
struct in_addr
{
uint32_t s_addr; // IP地址 以字符串形式来表示一个点分十进制。 IP地址的转化
};

IP地址转化的方法

uint32_t inet_addr (const char *__cp); // 将点分十进制的字符串转化为uint32_t类型
char * inet_ntoa (struct in_addr __in); // 将struct in_addr类型的变量转化为char*字符串

3. TCP的网络接口

/*
创建socket套接字
返回值: 成功返回文件描述符 socket 失败返回-1
domain: 协议簇 AF_INET TCP/IP协议
type: 具体的协议 SOCK_STREAM --> tcp SOCK_DGRAM --> UDP
protocol: 在前两个值的协议基础下的一个具体协议,一般默认设置为0
*/
int socket (int __domain, int __type, int __protocol);
/*
命令(绑定)socket套接字
返回值: 成功返回0, 失败返回-1
fd: socket方法返回的套接字的文件描述符
addr: 服务器的地址结构变量的地址 需要类型强转
len: addr的长度
*/
int bind (int __fd, struct sockaddr * __addr, socklen_t __len);
/*
启动监听方法
返回值: 成功返回0, 失败返回-1
fd: socket方法返回的套接字的文件描述符
n: 内核创建的用于维护已完成连接的客户端的个数: n+1
*/
int listen (int __fd, int __n);
/*
获取一个连接
返回值: 成功返回描述这个连接的文件描述符, 失败返回-1
fd: socket创建的文件描述符
addr: 用于保存客户端的地址信息
addr_len: addr的长度
*/
int accept (int __fd, struct sockaddr * __addr, socklen_t *__addr_len);
/*
读取数据
fd: 需要读取数据的文件描述符
buf: 读取的数据存储的缓冲区的首地址
n: 一次能够读取的数据长度,单位是字节
flag: 标志,默认给0
*/
ssize_t recv (int __fd, void *__buf, size_t __n, int __flags);
/*
发送数据
fd: 需要写入数据的文件描述符
buf: 写入的数据存储的缓冲区的首地址
n: 一次写入的真实数据长度,单位是字节
flag: 标志,默认给0
*/
ssize_t send (int __fd, const void *__buf, size_t __n, int __flags);
/*
发起连接的方法 -- 客户端程序使用
返回值: 成功返回0, 失败返回-1
fd: socket创建的文件描述符
addr: 服务器的地址信息
len: addr的长度
*/
int connect (int __fd, struct sockaddr * __addr, socklen_t __len);
// 关闭一个文件描述符
int close(int __fd);

4. TCP服务器端的编程流程

在这里插入图片描述

#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<unistd.h>
#include<string.h>

#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>



int main()
{
//创建用于监听的套接字,这个套接字是一个文件描述符,用于检测有没有客户端发起一个新的连接
    int listenfd = socket(AF_INET,SOCK_STREAM,0);
    assert(listenfd != -1);
    
    struct sockaddr_in addr;
    memset(&addr,0,sizeof(addr));
    addr.sin_family = AF_INET;
    addr.sin_port =htons(6000);//转化端口号
    addr.sin_addr.s_addr = inet_addr("127.0.0.1");//回环地址

// 将得到的监听的文件描述符和本地的IP端口进行绑定
    int res = bind(listenfd,(struct sockaddr*)&addr,sizeof(addr));
    assert(res != -1);
    
//设置监听(成功之后开始监听,监听的是客户端的连接)
    res = listen(listenfd,5);
    assert(res != -1);

//通信
    while (1)
    {
        struct sockaddr_in cli_addr;
        socklen_t cli_len = sizeof(cli_addr);
        int c = accept(listenfd,(struct sockaddr*)&cli_addr,&cli_len);
        if(c == -1)
        {
            printf("Get One Client Link Error\n");
            continue;
        }

        while (1)
        {
            char buff[128] = {0};
            int n = recv(c,buff,127,0);//读取数据放在buff中,一次读取127个
            if(n <= 0)
            {
                printf("Client will unlink\n");
                break;
            }
            printf("%d : %s\n",c,buff);
            send(c,"OK",2,0);
        }
        close(c);
    }
    
//断开连接,关闭套接字(四次挥手)
    close(listenfd);


    return 0;
}

5. TCP客户端的编程流程

在这里插入图片描述

#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<unistd.h>
#include<string.h>

#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>

int main()
{

//创建一个通信的套接字,需要指定服务器的IP和端口号y
    int sockfd = socket(AF_INET,SOCK_STREAM,0);
    assert(sockfd != -1);

    struct sockaddr_in ser_addr;
    memset(&ser_addr,0,sizeof(ser_addr));
    ser_addr.sin_family = AF_INET;
    ser_addr.sin_port =htons(6000);//转化端口号
    ser_addr.sin_addr.s_addr = inet_addr("127.0.0.1");//回环地址


//连接服务器,需要知道服务器绑定的IP和端口
    int res = connect(sockfd,(struct sockaddr*)&ser_addr,sizeof(ser_addr));
    assert(res != -1);

//通信
    while (1)
    {
        
        printf("input: ");
        char buff[128] = {0};
        fgets(buff,127,stdin);
        if(strncmp(buff,"end",3) == 0)
        {
            break;
        }

        send(sockfd,buff,strlen(buff) - 1,0);//\n不发

        memset(buff,0,128);
        recv(sockfd,buff,127,0);
        printf("%s\n",buff);
    }

//断开连接
    close(sockfd);
    
    return 0;
}

6.运行结果

在这里插入图片描述
在这里插入图片描述

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

C语言实现TCP编程 的相关文章

  • 检测客户端已与 TCP/IP 断开连接的正确方法

    我使用了异步 TCP IP 服务器 一切正常 但是当客户端由于错误或应用程序强制退出而断开连接时 它也会由于 IO IOException 类型的异常而关闭我的服务器 异常发生在以下子程序中 Private Sub ReadCallback
  • SCTP 与多宿主作为 TCP 的直接替代品

    SCTP具有本机多宿主支持 如果我理解正确的话 如果主接口出现故障 它将自动通过辅助 NIC 重新路由您的数据包 我通过编写一个自定义路由守护程序来使用 TCP 复制此功能 以便在我的主 NIC 出现故障时修改路由表 我想尝试使用SCTP反
  • 使用 OTP 原理的非阻塞 TCP 服务器

    我开始学习 Erlang 所以我尝试写 hello world 并发编程 IRC 机器人 我已经使用 Erlang 编写了一个 没有任何 OTP 细节 管理程序 应用程序等行为 我希望使用 OTP 原则重写它 但不幸的是我无法找出使用 OT
  • TCP打孔(NAT穿越)库什么的?

    我想用 C 进行 TCP 打洞 NAT 穿越 如果需要 可以使用集合服务器来完成 我发现http sharpstunt codeplex com http sharpstunt codeplex com 但无法让它发挥作用 理想情况下 我需
  • 指示远程主机已关闭连接的 NetworkStream.Read 的替代方案?

    关于使用以下命令处理 TCP IP 连接TcpClient类 除了等待之外 还有其他方法可以检查远程主机是否已关闭连接吗 NetworkStream Read返回0的方法 您可以使用IOControlCode KeepAliveValues
  • Indy TCP - 循环读取数据

    TCP 服务器每 8 毫秒连续发送一次数据帧 我想编写一个能够接收这些数据帧的客户端 Indy 9 中是否有任何程序可以知道缓冲区中是否有可用数据 我当前的程序如下 我正在使用线程 procedure TThreadRead Execute
  • Spring 集成超时客户端

    我的 Spring 集成场景是 使用自定义协议发送数据的数十个生产者 大小和内容 我必须解码这个自定义协议 然后处理结果 所以我尝试了很多配置 目前最好的配置如下
  • 定义新的套接字选项以在 TCP 内核代码中使用

    我正在尝试向 TCP 内核代码添加一些功能 在tcp input c 我希望我实现的代码仅在某些情况下运行 我想添加一个控制标志 可以从用户空间应用程序设置它 我 认为我 需要添加一个新的套接字选项 以便我可以完成以下操作setsockop
  • 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 打孔?

    问题如下 这是我当前的测试代码 但没有成功 static void Main string args if args Count 3 Console WriteLine Bad args var ep new IPEndPoint IPAd
  • wireshark 和 tcpdump -r:奇怪的 tcp 窗口大小

    我正在使用 tcpdump 捕获 http 流量 并且对 TCP 慢启动以及窗口大小如何增加感兴趣 sudo tcpdump i eth1 w wget tcpdump tcp and port 80 当我使用 Wireshark 查看转储
  • 为什么在数据包输入时 skb_buffer 需要跳过 20 个字节才能读取传输缓冲区?

    我正在 Linux 中编写一个网络模块 我发现只有在从 skb 缓冲区跳过 20 个字节后才能提取 tcp 标头 即使 API 是 skb transport header 其背后的原因是什么 有人可以详细解释一下吗 传出数据包不需要同样的
  • 通过 TCP 客户端套接字接收数据时出现问题

    我正在尝试用 C 语言编写一个 TCP 客户端程序 客户端将在其中启动 连接到服务器 然后它会发送一些信息 然后监听它收到的信息并做出相应的反应 我遇到麻烦的部分是持续聆听 这是我所拥有的 while 1 numbytes recv soc
  • 我的代码中某处存在无限循环

    我有这个 Java 游戏服务器 最多可处理 3 000 个 tcp 连接 每个玩家或每个 tcp 连接都有自己的线程 每个线程的运行情况如下 public void run try String packet char charCur ne
  • 如何使用 kotlin 通过 TCP 连接发送和接收字符串

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

    什么是 消息边界 在以下情况下 TCP 和 UDP 之间的区别之一是 UDP 保留消息 边界 我理解之间的区别TCP and UDP 但我不确定的定义 消息边界 由于 UDP 在每个单独的数据包中包含目的地和端口信息 因此是否可以为消息提供
  • 使用 iPhone 作为热点时 TCP 连接无法正常工作

    我正在开发一个 iOS 应用程序 它通过 TCP 套接字连接到在 Android 上运行的服务器应用程序 为了找到第二个设备的 IP 我使用 UDP 请求并接收服务器的 IP 当我将它们连接到 Wi Fi 网络或使用 Android 设备作
  • 是否可以通过互联网在两个移动设备 (iPhone) 之间连接套接字?

    是否可以通过互联网在两个移动设备 iPhone 之间连接套接字 我正在尝试发现每个设备的IP并直接连接 我知道可以使用 Bonjour 来完成 但这只适用于本地网络 我需要通过互联网在两个设备之间建立高速连接 Thanks 如果你有两个 I
  • 数据包丢失和数据包重复

    我试图找出数据包丢失和数据包重复问题之间的区别 有谁知道 数据包重复 是什么意思 和TCP检测到丢失时重传数据包一样吗 No In TCP 数据包 的传递是可靠的 我认为在这种情况下术语数据应该更好 因为它是面向流的协议 数据包丢失和重复是

随机推荐

  • STM32F103控制PCA9685产生16路PWM波控制SG90舵机

    STM32控制PCA9685产生16路PWM波控制SG90舵机 如果你能点开这篇文章 xff0c 说明你已经知道PCA9685是多么强大 xff0c NXP公司原本做这片芯片是为了提供给LED使用 xff0c 在其官方文档里也能看到所有PW
  • 从源代码来看HAL库函数(一) HAL基础函数

    从源代码来看HAL库函数 xff08 一 xff09 HAL基础函数 全局变量 IO uint32 t uwtick 这个变量充当了一个运行时长计数的作用 xff0c 每发生一次SysTick中断就会加一 xff0c 直至溢出 xff0c
  • 使用TCP+串口与板子进行网络通信

    最近做了一个嵌入式的project xff0c 大概要求就是做一个client端 xff0c 一个sensor端 xff0c 两者通过TCP UDP进行通信 xff0c 然后在client端输入不同的命令sensor需做出不同的处理 xff
  • 毕业论文格式(图片题注引用,表格,公式格式)

    本科毕业论文差不多写完了 xff0c 记录一下一些格式 xff0c 以后写作可能会用到 xff0c 就可以翻起来看看 首先 xff0c 如果可以找到一篇格式符合要求的word文档的话 xff0c 最简单的方法就是在这个文档的基础上进行内容的
  • 图像处理——相位恢复(GS,TIE,改进型角谱迭代法)(已更新代码)

    利用GS xff0c TIE xff0c 改进型角谱迭代算法进行相位恢复 角谱传播理论 角谱传播理论可以翻阅傅里叶光学的书 xff0c 就能找到定量分析的计算公式 xff0c 可以分析某个平面的角谱垂直传播到另外一个平面的角谱 xff0c
  • 串口应用:遵循uart协议,发送多个字节的数据(状态机)

    上一节中 xff0c 我们遵循uart协议 xff0c 它发送一次只能发送6 7 8位数据 xff0c 我们不能随意更改位数 xff08 虽然在代码上可行 xff09 xff0c 不然就不遵循uart协议了 xff0c 会造成接收端无法接收
  • 数码管动态显示Verilog实现(参考小梅哥教程)(视觉暂留)

    一个数码管有八个引脚 xff0c 控制八段二极管的亮灭 xff0c 用以显示需要的数字 当有N个数码管时 xff0c 一个一个控制的话需要N x 8 个引脚 xff0c 消耗资源较多 因此可以利用动态显示的方案通过人眼的视觉暂留特性达到静态
  • 彻底理解DDS(信号发生器)的fpga实现(verilog设计代码)

    DDS xff08 Direct Digital Synthesis xff09 是一种把一系列数字信号通过D A转换器转换成模拟信号的数字合成技术 它有查表法和计算法两种基本合成方法 在这里主要记录DDS查表法的fpga实现 查表法 xf
  • HDMI/DVI

    一 基础知识 1 历史 早期在FPGA芯片上实现HDMI控制显示是使用HDMI发送芯片 xff0c eg xff1a ADV7513 sil9022 xff0c CH7301等 用之前VGA控制中输出的RGB信号 行场同步信号和使能信号输入
  • HDMI/DVI____TMDS编码

    一 编码步骤 xff1a 基本方法 xff1a 取第一位数据为初值 xff0c 接下来输入的每一位与前一导出的位 xff08 根据判断条件 xff09 进行异或XOR或者同或XNOR xff08 最小化传输 xff0c 减少0 1翻转 xf
  • HDMI/DVI____串行发送器

    一 功能 xff1a 把10bit数据转化为串行数据在一个时钟周期全部输出 xff08 先输出高位 xff0c 再输出低位 xff09 二 框图 二 思路 对于TMDS编码器 xff0c 在每一个输入时钟周期 xff0c 输入一次数据到TM
  • keil添加新文件.c.h

    文章目录 添加文件到组中1 双击组名称2 点击快捷键 添加头文件路径 h1 点击魔术棒快捷键2 头文件加 添加文件到组中 1 双击组名称 双击组名称 xff0c 打开弹窗 xff0c 然后选择相应的组中的新文件 xff0c 在点击ADD 2
  • QT常用控件(二)——自定义控件封装

    引言 Qt已经提供了很多的基础控件供开发使用 xff0c 而Qt原生的控件有时候并不能满足我们的需求 xff0c 特别是在工业的运用上 xff0c 比如我们需要一个日期时间的选择器 xff0c Qt虽然已经提供了原生的QDateTime控件
  • STM32之串口通信USART模块学习(1)

    一 通信接口 通信的目的 xff1a 将一个设备的数据传送到另一个设备 xff0c 扩展硬件系统通信协议 xff1a 制定通信的规则 xff0c 通信双方按照协议规则进行数据收发 单端信号通信的双方必须要共地 xff0c 因为都是对GND的
  • 2019电赛总结(一)

    2019电赛总结 xff08 一 xff09 文章目录 2019电赛总结 xff08 一 xff09 4 那之前5 电赛初期6 电赛中期7 电赛强化练习8 电赛预热阶段8月初9 那以后 4 那之前 2019电赛总结 序 xff09 5 电赛
  • 统计从键盘输入的一行字符中小写字母,大写字母,数字字符和其它字符的个数。

    统计从键盘输入的一行字符中小写字母 xff0c 大写字母 xff0c 数字字符和其它字符的个数 C语言实现 vs 2019 span class token macro property span class token directive
  • c语言求1~10的阶乘和

    求1 43 2 43 3 43 43 10 的和 span class token macro property span class token directive keyword include span span class toke
  • C和Cpp区别

    1 输入 xff0c 输出不同 xff08 out xff0c put xff09 c语言 xff1a include lt stdio h gt scanf 34 d 34 amp a printf 34 a 61 d n 34 a cp
  • C++实现基于顺序搜索的动态分区分配算法

    目录 1 需求分析 2 代码实现 3 测试用例 4 总结与收获 1 需求分析 动态分区分配又称为可变分区分配 xff0c 他是根据进程的实际需要 xff0c 动态地为之分配内存空间 在实现动态分区分配时 xff0c 将涉及到分区分配中所有的
  • C语言实现TCP编程

    C语言实现TCP编程 1 主机字节序和网络字节序2 套接字的地址结构IP地址转化的方法 3 TCP的网络接口4 TCP服务器端的编程流程5 TCP客户端的编程流程6 运行结果 1 主机字节序和网络字节序 主机字节序 xff1a 不同的芯片