【C语言】实现linux下的基于C语言的一个简单的TCP客/服 端的通信

2023-05-16

对于基础的好的朋友可以直接取代码,如果想要看详细解析的朋友可以详看下方的解析

TCP服务端代码:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <netinet/in.h>

/*
@brief TCP通信服务端
*/
int main()
{
	//1.创建套接字
	int sockfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
	if(sockfd == -1)
	{
		perror("sockfd failed!\n");
		return 0;
	}

	//2.绑定端口
	struct sockaddr_in serv_addr;//1.见最下方解析
	memset(&serv_addr, 0, sizeof(serv_addr));//清空结构体

	serv_addr.sin_family = AF_INET;
	serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1");//记住服务端绑定的是自己的地址,127.0.0.1就是指代的本地地址,如果是多网卡的情况,使用htonl(INADDR_ANY),表示将本地所有地址都绑定起来用于监听
	serv_addr.sin_port = htons(1234);

	bind(sockfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr));//绑定套接字与端口

	//3.服务端开始监听:所谓的监听就是等待客户端的连接
	listen(sockfd, 20);

	//4.接受客户端的连接请求
	struct sockaddr_in client_addr;//这里直接定义一个地址结构体用于存储客户端的地址信息
	socklen_t c_len = sizeof(client_addr);

	int connect_sockfd = accept(sockfd, (struct sockaddr*)&client_addr, &c_len);
    if(connect_sockfd == -1)
    {
        perror("connect_sockfd failed!\n");
        return 0;
    }

	//5.收发数据
	char send_buf[32] = {0};//发送数据缓冲区
	while(1)
	{
		scanf("%s", send_buf);
		write(connect_sockfd, send_buf, sizeof(send_buf));//发送

		if(strcmp(send_buf, "over") == 0)//设置发送 over 之后自动结束通信
		{
			write(connect_sockfd, send_buf, sizeof(send_buf));
			break;
		}
	}

	//6.关闭套接字
	close(connect_sockfd);
	close(sockfd);

	return 0;
}

TCP客户端代码:

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

/*
@brief TCP通信客户端
*/
int main()
{
	//1.创建套接字
	int sockfd = socket(AF_INET, SOCK_STREAM, 0);
	if(sockfd == -1)
	{
		perror("sockfd failed!\n");
		return 0;
	}

	//2.连接服务端
	struct sockaddr_in serv_addr;
	memset(&serv_addr, 0, sizeof(serv_addr));

	serv_addr.sin_family = AF_INET;
	serv_addr.sin_addr.s_addr =  inet_addr("127.0.0.1");//服务端地址
	serv_addr.sin_port = htons(1234);

	connect(sockfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr));//连接服务端

	//3.收发数据
	char recv_buf[32] = {0};

	while(1)
	{
		memset(recv_buf, 0, sizeof(recv_buf));//清空之后再接收数据
		read(sockfd, recv_buf, sizeof(recv_buf)-1);//接收数据
		if(strlen(recv_buf) != 0)
		{
			printf("recv: %s\n", recv_buf);
		}
		

		if(strcmp(recv_buf, "over") == 0)
		{
			break;
		}
	}

	//4.关闭套接字
	close(sockfd);

	return 0;
}

这是最基本的TCP通信协议了,对这份通信代码,能解析的点不多:

首先第一点:struct sockaddr_in serv_addr; 这个结构体是定义在<netinet/in.h>头文件中

大家可以从代码中看出  sockaddr_in 这个结构体中的成员就是ip地址簇、端口号、ip地址。

struct sockaddr_in
 
{
 
    short sin_family;/*Address family一般来说AF_INET(地址族)PF_INET(协议族)*/
 
    unsigned short sin_port;//端口号
     
    struct in_addr sin_addr;//ip地址
 
    unsigned char sin_zero[8];//没有实际意义,只是为了跟SOCKADDR结构在内存中对齐
 
};

不过有趣的是,这个结构体成员之一的ip地址,是用另外一个结构体定义的,以下是在linux下的对于这个结构体的定义(不同的操作系统这个定义有稍些差异),这里可以看出另定义一个结构体在linux下其实是没什么必要的,不过官方如此定义,那么在原生的时候这个定义肯定有其他的不足的地方,所以才会另外定义一个结构体来存储ip地址,大家可以不用纠结

typedef uint32_t in_addr_t;
struct in_addr
{
    in_addr_t s_addr;//ip地址
};

其实很明显可以看出,这个结构体只有一个成员就是 s_addr,也就是ip地址,是一个无符号的32位整型,用小白看的懂的代码写出来就是 unsigned int   s_addr

解析的第二点:各个函数的原型以及功能介绍

服务端:


int socket(int af, int type, int protocol);//创建一个套接字用于通信
  

参数解析:

af 为地址族(Address Family),也就是 ip地址类型,常用的有 AF_INET 和 AF_INET6。分别代表ipv4、ipv6


type 为数据传输方式,常用的有 SOCK_STREAM 和 SOCK_DGRAM,分别代表TCP数据流传输和UDP数据报传输


protocol 表示传输协议,常用的有 IPPROTO_TCP 和 IPPTOTO_UDP,分别表示 TCP 传输协议和 UDP 传输协议。我们在使用的时候既可以写明,也可以用 0 表示让系统自动推导该用什么协议(因为type已经定义了用TCP数据流方式传输)


int bind(int sock, struct sockaddr *addr, socklen_t addrlen);//绑定一个 地址+端口 作为自己的传输数据的端点  

参数解析:

sock 为创建的套接字

addr 本身为前面介绍的结构体 sockaddr_in,但大家可以看出,这和定义的bind函数的参数类型不匹配啊?是的,不匹配,所以我们在用 bind( )的时候需要将 addr 从 sockaddr_in 强制转换为 sockaddr 类型。

struct sockaddr

{

        sa_family_t sin_family; //地址族(Address Family),也就是地址类型

        char sa_data[14]; //IP地址和端口号

};

可以看出 sockaddr 和 sockaddr_in 这两个结构体并没有什么太大的不一样,只不过 sockaddr  将 IP地址和端口 定义在了一起


addrlen 表示 定义的服务端的结构体 sockaddr_in 的大小

int listen(int sock, int backlog);//监听,等待客户端的连接

参数解析:

sock 为需要进入监听状态的套接字


backlog 为客户端请求队列的最大长度,即允许一次性有多少个客户端与服务端建立连接,这个数值一般随心,1,2,10,20等等,这与内核的缓冲区的大小有关 

int accept(int sock, struct sockaddr *addr, socklen_t *addrlen);//接受来自客户端的连接,其参数定义与 bind ( ) 相同

参数解析:

sock 为创建的套接字

addr 为地址结构体 sockaddr_in,详见bind函数解析,但是这里大家要注意,这里接受来自客户端的连接,这个地址结构体不再是 服务端的地址结构体, 而是客户端的地址结构体


addrlen 表示 定义的服务端的结构体 sockaddr_in 的大小

客户端:


int connect(int sock, struct sockaddr *serv_addr, socklen_t addrlen);  

参数解析:

sock 为创建的套接字

addr 为服务端地址结构体 sockaddr_in,详见bind函数解析


addrlen 表示 定义的服务端的结构体 sockaddr_in 的大小

参考百度百科和C语言中文网

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

【C语言】实现linux下的基于C语言的一个简单的TCP客/服 端的通信 的相关文章

  • 全国DNS服务器IP地址大全、公共DNS大全

    各省公共DNS服务器IP大全 名称各省公共DNS服务器IP大全 114 DNS114 114 114 114114 114 115 115阿里 AliDNS223 5 5 5223 6 6 6百度 BaiduDNS180 76 76 76
  • 如何在CentOS7上禁用或关闭SELinux

    介绍 SELinux 是内置于 Linux 内核中的强制访问控制 MAC 执行器 它限制了可能对系统构成威胁的个别服务的权限 没有 SELinux 的 CentOS 系统依赖于其所有特权软件应用程序的配置 单个错误配置可能会危及整个系统 为
  • 运维常用的 35 个Linux Shell 脚本,一定能帮到你!

    作为一名 Linux 工程师 xff0c 会写好的脚本不仅能提高工作效率 xff0c 还能有更多的时间做自己的事 最近在网上冲浪的时候 xff0c 也注意收集一些大佬写过的脚本 xff0c 汇总整理一下 xff0c 欢迎收藏 xff0c 与
  • 超好用的开源 IP 地址管理系统,告别传统 Excel 统计方式!

    来自 xff1a 释然IT杂谈 一 前言 xff1a 对于运维管理人员 xff0c ip地址进行管理很重要 xff0c 很多公司都是采用电子文档的形式 xff0c 以手工更新为主 xff0c 对ip地址和子网的实际使用情况无法进行有效的实时
  • Linux运维从入门到精通,看这一篇就够了~

    作为一名 Linux 运维工程师 xff0c 总是会有种 书到用时方恨少 的感觉 xff0c 其根本原因还是技能掌握的不够扎实 所以运维朋友一定要多学习 xff0c 提升技能 xff0c 下面分享一份专门针对运维朋友的资料包 xff0c 相
  • K8S CPU 请求和限制,是否有很好的选择?

    Limits 和 Requests 并不是 CPU 管理的灵丹妙药 xff0c 在某些情况下 xff0c 其他替代方案可能是更好的选择 在这篇博文中 xff0c 您将了解到 xff1a CPU requests 如何工作CPU limits
  • 作为一名Linux用户,你得了解这15个工具!

    来源 xff1a 浩道Linux 在普通人眼里 xff0c 使用Linux系统的用户本身已经很有 极客范儿 了 xff0c 但是在技术人员眼中 xff0c 这只是很普通的层级 使用本文推荐的几个Linux系统下的工具 xff0c 能让你瞬间
  • 虚拟网络namespace 到bridge

    前言 容器的网络是一大难点 xff0c 不管是docker 还是kubernetes 都绕不开计算机网络 以下的介绍主要以计算机网络的namespace 和bridge 两个方面来展开介绍 xff0c 方便深入理解容器的网络原理 1 nam
  • 用OpenCV实现目标追踪的八种方法(转)

    原文地址 xff1a http m elecfans com article 722414 html 编者按 xff1a 目标跟踪作为机器学习的一个重要分支 xff0c 加之其在日常生活 军事行动中的广泛应用 xff0c 很多国内外学者都对
  • turbostat超频检测工具

    介绍 turbostat为Intel提供的超频检测工具 xff0c 可以真正在Linux下获取睿频频率的工具 由下可知 xff1a 物理cpu个数为2 xff0c 核心数为14 xff0c 支持超线程 xff0c 逻辑cpu数为56 xff
  • C# HttpClient Digest 摘要认证 Cookie设置

    C HttpClient Digest 摘要认证 Cookie设置 1 创建凭证信息集 2 创建HttpClientHandler 3 创建HttpClient 4 发生请求 span class token comment 创建凭证信息集
  • MongoDB 批量操作(bulkWrite)

    一 概述 mongodb 3 2 版中的新版本提供了db collection bulkWrite 方法提供了执行批量插入 更新和删除操作的能力 mongodb 还支持批量插入 db collection insertMany 1 1 语法
  • Linux动态库的编译与使用(两种方式:链接进可执行程序、动态加载)

    第一步 xff1a 编写Linux程序库 文件1 动态库接口文件 span class token comment 动态库接口文件getmaxlen h span span class token macro property span c
  • ES 索引文档,按_id查找、更新、删除文档

    一 索引 xff08 新建 xff09 文档 通过使用 index API xff0c 文档可以被 索引 存储和使文档可被搜索 但是首先 xff0c 我们要确定文档的位置 正如我们刚刚讨论的 xff0c 一个文档的 index type 和
  • ES排序

    排序 为了按照相关性来排序 xff0c 需要将相关性表示为一个数值 在 Elasticsearch 中 xff0c 相关性得分 由一个浮点数进行表示 xff0c 并在搜索结果中通过 score 参数返回 xff0c 默认排序是 score
  • ES基于completion suggest实现搜索提示

    Term Suggester xff0c 基于编辑距离 xff0c 对analyze过的单个term去提供建议 xff0c 并不会考虑多个term 词组之间的关系 quert gt queryPhrase Suggester xff0c 在
  • 时间间隔宏计算

    对结果按时间间隔分桶 span class token macro property span class token directive keyword define span TIME INTERVAL a b a lt lt 32 4
  • 容器环境下IP跨网闸映射kafka部署

    一 listeners 和 advertised listeners 在公司内网部署 kafka 集群只需要用到 listeners xff0c 内外网需要作区分时才需要用到advertised listeners listeners 学名
  • C/C++ 中头文件相互包含引发的问题(was not declared in this scope)

    问题引入 最近遇到一个问题 xff0c 重构的代码编译报定义的某个宏was not declared in this scope xff0c 但是明明已经引入了包含此宏的头文件 问题分析 转载内容 我把问题脱离于项目简单描述一下 xff1a
  • 字符的全排列、字符的组合

    一 字符的全排列 题目描述 输入一个字符串 按字典序打印出该字符串中字符的所有排列 例如输入字符串abc 则打印出由字符a b c所能排列出来的所有字符串abc acb bac bca cab和cba 输入描述 输入一个字符串 长度不超过9

随机推荐

  • HTTP带用户名和密码请求

    import java io IOException import org apache commons codec binary Base64 import com cn mid system urls UrlUtils import o
  • n*m的格子中正方形个数和长方形个数

    问题描述 1 xff0e 设有一个nm方格的棋盘 xff08 1 m n 100 xff09 求出该棋盘中包含多少个正方形 多少个长方形 xff08 不包括正方形 xff09 例如 xff1a 当n 61 2 xff0c m 61 3时 正
  • Linux数字权限

    linux系统文件夹 从左至右 xff0c 第一位数字代表文件所有者的权限 xff1b 第二位数字代表同组用户的权限 xff1b 第三位数字代表其他用户的权限 而具体的权限是由数字来表示的 xff1a 读取的权限等于4 xff0c 用r表示
  • 八大排序算法C语言实现

    1 插入排序 1 1 直接插入排序 基本原理 xff1a 将第n个数插入已经排序好的 xff0c 长度为n 1的序列中 从n 1长度的序列中查找出待插入的元素应该插入的位置 xff1b 给插入元素腾出空间 操作方法 xff1a 从第2个数开
  • CLion下的gtest测试

    在mac环境中 xff0c 使用CLion编译的简单gtest程序 一 下载gtest源码 加入工程中 xff1a 二 编写CMakeList txt 文件 在文件中添加头文件和链接库文件 xff0c 并将链接库文件与目标文件进行链接 sp
  • python中json与dict的互相转换(编码与解码)及其简单实现

    在json模块中 将json转换为dict数据的方法有 xff1a load loads xff08 xff09 其中 xff0c load 方法从文件中提取数据进行转换 将dict转换为json数据的方法有 xff1a dump dump
  • gtest中ASSERT与EXPECT断言的区别

    参考资料查找到ASSERT断言与EXPECT断言的区别 xff1a ASSERT 系列的断言 xff0c 当检查点失败时 xff0c 退出当前函数 xff08 注意 xff1a 并非退出当前案例 xff09 EXPECT 系列的断言 xff
  • gtest参数化

    步骤 xff1a 1 创建一个类 xff0c 继承testing TestWithParam xff0c T是你需要参数化的参数类型 xff0c 比如参数类型为int 2 使用新宏TEST P替代TEST 在TEST P宏里 xff0c 可
  • gtest中字符串比较是否相等

    1 EXPECT EQ val1 xff0c val2 xff09 class StringCmpTest span class token punctuation span public testing span class token
  • 白盒测试——逻辑覆盖

    白盒测试中的逻辑覆盖有以下六种方法 xff1a 1 语句覆盖 xff1a 每个可执行语句至少被执行一次 2 判定覆盖 xff1a 每个判定的每个分支都至少执行一次 3 条件覆盖 xff1a 判定式中每个条件的每个分支至少执行一次 4 判定条
  • 计算机网络面试题整理

    面试很多时候被问到的问题 xff0c 感觉都没答好 xff0c 统一整理一下 更新 8 23 GET和POST的区别 xff1f GET和POST方法没有实质上区别 xff0c 只是报文格式不同 GET和POST是HTTP协议中的两种请求方
  • 【C语言】c/c++中常用的预定义宏:__LINE__, __func__, __FILE__, __DATE__, __TIME__

    ANSI C标准中的预定义宏 xff08 也是常用的 xff09 xff1a LINE xff1a 在代码中插入当前行号 func xff1a 在代码中插入当前行所在的函数的函数名 FILE xff1a 在代码中插入当前文件的文件名 DAT
  • 无人机入门知识

    无人机入门知识 无人机的定义 现在提到的 无人机 xff0c 通常是说 无人飞行载具 xff08 Unmanned Aerial Vehicle xff0c 简称UAV xff09 xff0c 或称无人飞机 无人飞机系统 xff08 Unm
  • http协议

    一 认识url url被称为统一资源定位符 xff0c 用来表示从互联网上得到的资源位置和访问这些资源的方法 他的表示方法一般为 xff1a span class token operator lt span 协议 span class t
  • 大小端区别和判断

    在代码中看到往寄存器写数据的时候 xff0c 使用到 volatile uint32 t address 61 cpu to le32 value xff0c 进一步追踪 xff0c if BYTE ORDER 61 61 LITTLE E
  • 结构体对齐详解

    1 结构体数据成员对齐的意义 许多实际的计算机系统对基本类型数据在内存中存放的位置有限制 xff0c 它们会要求这些数据的起始地址的值是某个数k的倍数 xff0c 这就是所谓的内存对齐 xff0c 而这个k则被称为该数据类型的对齐模数 al
  • C语言基础之格式化占位符

    在 printf 系列函数中 xff0c 下列哪个格式化占位符有可能导致内存任意写风险 A A n B d C p D s 使用printf修改变量的值 VS2008中使用 n输出遇到的问题及解决方法 include lt stdio h
  • 不常用的访问控制方式——http auth

    今天遇到一个http auth方式的访问控制 xff0c 访问页面时出现输入用户名与密码的验证 xff1a 使用ncrack爆破登陆后 xff0c 当想要爆破目录时 xff0c 必须每次请求都带着authorication头 xff0c 使
  • 数据库中字符串匹配函数like、rlike、instr、regexp_extract

    instr 简介 MySQL hive中函数 xff0c instr str substr position occurrence 其中str代表从哪个字符串中搜索 xff0c substr代表搜索哪个子字符串 xff0c 返回值为子字符串
  • 【C语言】实现linux下的基于C语言的一个简单的TCP客/服 端的通信

    对于基础的好的朋友可以直接取代码 xff0c 如果想要看详细解析的朋友可以详看下方的解析 TCP服务端代码 xff1a include lt stdio h gt include lt string h gt include lt stdl