IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 网络协议 -> TCP/UDP协议的网络通信 -> 正文阅读

[网络协议]TCP/UDP协议的网络通信

网络编程:

? ? 底层遵循TCP/IP协议,在系统层上以socket接口方式呈现

? ? 基于TCP协议的网络通信模型:

? ? ? ? 服务器 ? ? ? ? ? ? ? ? ? ? ?????????????????客户端

? ? 创建socket对象 ? ? ? ? ? ? ???????????创建socket对象

? ? 准备通信地址(端口号+IP地址) ?准备对方通信地址

? ? 绑定socket和地址 ? ? ? ? ? ? ? ? ?????????...

? ? 设置监听和排队数量 ? ? ? ? ? ? ? ????????? ...

? ? 等待客户端连接 ? ? ? ? ? ? ?????????????????连接服务器

? ? 分配新的socket对象+

? ? 开辟新的进程或者线程服务 ? ????????? ...

? ? 接收请求 ? ? ? ? ? ? ? ? ? ?????????????????????????发送请求

? ? 响应请求 ? ? ? ? ? ? ? ? ? ?????????????????????????接收响应

? ? 关闭socket ? ? ? ? ? ? ? ? ?????????????????????????关闭socket

? ? 使用到的函数:

? ? int socket(int domain, int type, int protocol);

? ? 功能:创建socket对象

? ? domain:

? ? ? ? AF_INET ? ? ? ? ? ? 基于IPv4地址通信

? ? type:

? ? ? ? SOCK_STREAM ? ? ? ? 数据流协议 TCP

? ? protocol:

? ? ? ? 特殊通信协议,一般不用,写0即可

? ? 返回值:成功返回socket描述符,失败返回-1

? ? //网络地址结构体类型

? ? #include <netinet/in.h>

? ? struct sockaddr_in {

? ? ? ? __kernel_sa_family_t ?sin_family; //AF_INET

? ? ? ? __be16 ? ? ? ?sin_port; ? //端口号 ?大端数据

? ? ? ? struct in_addr ? ?sin_addr; ? //IP地址 ?大端数据

? ? };

? ? struct in_addr {

? ? ? ? __be32 ?s_addr;

? ? };

? ? 大小端数据转换函数:

? ? #include <arpa/inet.h>

? ? uint32_t htonl(uint32_t hostlong);

? ? 功能:把4字节的本地字节序转换成网络字节序

? ? uint16_t htons(uint16_t hostshort);

? ? 功能:把2字节的本地字节序转换成网络字节序

? ? uint32_t ntohl(uint32_t netlong);

? ? 功能:把4字节的网络字节序转换成本地字节序

? ? uint16_t ntohs(uint16_t netshort);

? ? 功能:把2字节的网络字节序转换成本地字节序

? ? IP地址转换函数:

? ? in_addr_t inet_addr(const char *cp);

? ? 功能:把字符串格式的点分十进制表示的IP地址转换成整数形式的IP地址(大端)

? ? char *inet_ntoa(struct in_addr in);

? ? 功能:把整数形式的IP地址转换成字符串格式的点分十进制表示的IP地址

? ? int listen(int sockfd, int backlog);

? ? 功能:监听socket

? ? sockfd:socket描述符

? ? backlog:等待连接socket的排队数量,默认最大128

? ? 返回值:成功返回0,失败返回-1

? ? int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);

? ? 功能:等待连接,数据流通信时使用

? ? sockfd:受监听的socket描述符

? ? addr:获取客户端的地址

? ? addrlen:既是输入,也是输出

? ? ? ? 1、既告诉accept函数当前计算机的地址结构体的字节数

? ? ? ? 2、同时也能获取客户端的地址结构体字节数

? ? 返回值:连接成功返回一个新的连接后的socket描述符,连接失败返回-1

? ? 注意:如果没有连接,则阻塞

? ? int connect(int sockfd, const struct sockaddr *addr,socklen_t addrlen);

? ? 功能:连接服务器

? ? sockfd:socket描述符

? ? addr:服务器的公网IP地址结构体指针

? ? addrlen:地址结构体的字节数,用于区分sockaddr_un还是sockaddr_in

? ? 返回值:成功0,失败-1

? ? 注意:TCP收发数据可以继续使用read、write

? ? ssize_t send(int sockfd, const void *buf, size_t len, int flags);

? ? 功能:TCP协议通信时专用的数据发送函数

? ? sockfd:连接成功的socket描述符

? ? buf:待发送数据的首地址

? ? len:要发送的字节数

? ? flags:

? ? ? ? 0 ? 阻塞发送

? ? ? ? 1 ? 不阻塞发送

? ? 返回值:成功发送的字节数

? ? ? ? ? ? -1 出现错误

? ? ? ? ? ? 0 ?连接断开

? ? ssize_t recv(int sockfd, void *buf, size_t len, int flags);

? ? 功能:TCP协议通信时专用的数据接收函数

? ? sockfd:连接成功的socket描述符

? ? buf:存储数据缓冲区内存首地址

? ? len:缓冲区大小

? ? flags:

? ? ? ? 0 ? 阻塞接收

? ? ? ? 1 ? 不阻塞接收

? ? 返回值:成功接收的字节数

? ? ? ? ? ? -1 出现错误

? ? ? ? ? ? 0 ?连接断开

? ? ?TCP服务器端:

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

typedef struct sockaddr* SP;

void server_cli(int cli_fd)
{
	char buf[4096] = {};
	size_t buf_size = sizeof(buf);

	for(;;)
	{
		//	接收请求
		int ret = recv(cli_fd,buf,buf_size,0);
		if(0 == strcmp(buf,"quit") || 0 >= ret)
		{
			printf("客户端%d退出!\n",cli_fd);
			break;
		}
		printf("from %d recv:%s bits:%d\n",
			cli_fd,buf,ret);

		//	响应请求
		strcat(buf," from:server");
		ret = send(cli_fd,buf,strlen(buf)+1,0);
		if(0 >= ret)
		{
			printf("客户端%d退出!\n",cli_fd);
			break;
		}
	}
	close(cli_fd);
	exit(0);
}

int main(int argc,const char* argv[])
{
	//	创建socket
	int sockfd = socket(AF_INET,SOCK_STREAM,0);
	if(0 > sockfd)
	{
		perror("socket");
		return EXIT_FAILURE;
	}

	//	准备本机通信地址
	struct sockaddr_in addr = {};
	addr.sin_family = AF_INET;
	addr.sin_port = htons(5566);
	//	本机ip
	addr.sin_addr.s_addr = inet_addr("172.16.83.85");
	socklen_t addrlen = sizeof(addr);
	
	//	绑定
	if(bind(sockfd,(SP)&addr,addrlen))
	{
		perror("bind");
		return EXIT_FAILURE;
	}

	//	监听
	if(listen(sockfd,5))
	{
		perror("listen");
		return EXIT_FAILURE;
	}

	for(;;)
	{
		//	等待连接
		struct sockaddr_in cli_addr = {};
		int cli_fd = accept(sockfd,(SP)&cli_addr,&addrlen);
		if(0 > cli_fd)
		{
			perror("accept");
			continue;
		}
		
		//	创建进程服务客户端
		if(0 == fork())
		{
			server_cli(cli_fd);	
		}
	}
}

? ? TCP客户端:

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

typedef struct sockaddr* SP;

int main(int argc,const char* argv[])
{
	//	创建socket
	int sockfd = socket(AF_INET,SOCK_STREAM,0);
	if(0 > sockfd)
	{
		perror("socket");
		return EXIT_FAILURE;
	}

	//	准备服务器公网通信地址
	struct sockaddr_in addr = {};
	addr.sin_family = AF_INET;
	addr.sin_port = htons(5566);
	addr.sin_addr.s_addr = inet_addr("47.97.229.46");
	socklen_t addrlen = sizeof(addr);
	
	//	连接服务器
	if(connect(sockfd,(SP)&addr,addrlen))
	{
		perror("connect");
		return EXIT_FAILURE;
	}
	
	char buf[4096] = {};
	size_t buf_size = sizeof(buf);

	for(;;)
	{
		printf(">>>");
		fgets(buf,buf_size,stdin);
		//	发送请求
		int ret = send(sockfd,buf,strlen(buf)+1,0);
		if(0 >= ret)
		{
			printf("服务器正在升级,请稍候再尝试!\n");
			break;
		}
		if(0 == strncmp(buf,"quit",4))
		{
			printf("结束通信!\n");
			break;
		}

		//	接收响应
		ret = recv(sockfd,buf,buf_size,0);
		if(0 >= ret)
		{
			printf("服务器正在升级,请稍候再尝试!\n");
			break;
		}
		printf("recv:%s bits:%d\n",buf,ret);
	}
	close(sockfd);
}

? ? 基于UDP协议的网络通信编程模型:

? ? ? ? 接收端 ? ? ? ? ? ? 发送端

? ? ?创建socket ? ? ? ? ?创建socket

? ? ?准备通信地址 ? ? ? ? 准备通信地址

? ? ?绑定 ? ? ? ? ? ? ? ? ?...

? ? ?接收请求 ? ? ? ? ? ? 发送请求

? ? ?响应请求 ? ? ? ? ? ? 接收响应

? ? ?关闭socket ? ? ? ? ? 关闭socket

? ? int socket(int domain, int type, int protocol);

? ? 功能:创建socket对象

? ? domain:

? ? ? ? AF_INET ? ? ? ? ? ? 基于IPv4地址通信

? ? type:

? ? ? ? SOCK_DGRAM ? ? ? ? 数据流协议 UDP

? ? protocol:

? ? ? ? 特殊通信协议,一般不用,写0即可

? ? 返回值:成功返回socket描述符,失败返回-1

? ? UDP专属的数据发送接收函数:

? ? ssize_t sendto(int sockfd,const void *buf,size_t len,int flags,const struct sockaddr *dest_addr,socklen_t addrlen);

? ? 功能:UDP协议发送数据

? ? sockfd:socket描述符

? ? buf:待发送数据的首地址

? ? len:待发送数据的字节数

? ? flags:是否阻塞 一般写0阻塞即可

? ? dest_addr:通信目标的地址

? ? addrlen:地址结构体的字节数

? ? 返回值:成功发送的字节数

? ? ? ? 0 ? 通信关闭

? ? ? ? -1 ?出现错误

? ? ssize_t recvfrom(int sockfd,void *buf,size_t len,int flags,struct sockaddr *src_addr,socklen_t *addrlen);

? ? 功能:UDP协议接收数据

? ? sockfd:socket描述符

? ? buf:存储接收数据的缓冲区内存首地址

? ? len:缓冲区的字节数

? ? flags:是否阻塞 一般写0阻塞即可

? ? src_addr:存储发送者的地址

? ? addrlen:既是输入,也是输出

? ? ? ? 1、既告诉当前src_addr结构体的字节数

? ? ? ? 2、同时也能接收到发送者的地址结构体字节数

? ? 返回值:成功接收的字节数

? ? ? ? 0 ? 通信关闭

? ? ? ? -1 ?出现错误

UDP服务器:

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

typedef struct sockaddr* SP;

int main(int argc,const char* argv[])
{
	//	创建socket
	int sockfd = socket(AF_INET,SOCK_DGRAM,0);
	if(0 > sockfd)
	{
		perror("socket");
		return EXIT_FAILURE;
	}
	
	//	准备本机通信地址
	struct sockaddr_in srv_addr = {},cli_addr = {};
	srv_addr.sin_family = AF_INET;
	srv_addr.sin_port = htons(7788);
	srv_addr.sin_addr.s_addr = inet_addr("172.16.83.85");
	socklen_t addrlen = sizeof(srv_addr);

	//	绑定
	if(bind(sockfd,(SP)&srv_addr,addrlen))
	{
		perror("bind");
		return EXIT_FAILURE;
	}

	char buf[4096] = {};
	size_t buf_size = sizeof(buf);

	for(;;)
	{
		//	接收数据和对方的地址
		int ret = recvfrom(sockfd,buf,buf_size,0,(SP)&cli_addr,&addrlen);
		if(0 >= ret)
		{
			printf("网络异常,通信结束!");
			close(sockfd);
			return EXIT_FAILURE;
		}
		printf("from %s recv:[%s] bits:%d\n",
			inet_ntoa(cli_addr.sin_addr),buf,ret);

		//	返回响应
		strcat(buf,"from udpS");
		ret = sendto(sockfd,buf,strlen(buf)+1,0,(SP)&cli_addr,addrlen);
		if(0 >= ret)
		{
			printf("对方网络异常!\n");	
		}
	}
}	

UDP客户端:

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

typedef struct sockaddr* SP;

int main(int argc,const char* argv[])
{
	//	创建socket
	int sockfd = socket(AF_INET,SOCK_DGRAM,0);
	if(0 > sockfd)
	{
		perror("socket");
		return EXIT_FAILURE;
	}
	
	//	准备服务器通信地址
	struct sockaddr_in srv_addr = {};
	srv_addr.sin_family = AF_INET;
	srv_addr.sin_port = htons(7788);
	srv_addr.sin_addr.s_addr = inet_addr("47.97.229.46");
	socklen_t addrlen = sizeof(srv_addr);

	char buf[4096] = {};
	size_t buf_size = sizeof(buf);

	for(;;)
	{
		printf(">>>");
		scanf("%s",buf);
		if(0 == strcmp(buf,"quit"))
		{
			printf("结束通信!\n");
			close(sockfd);
			return EXIT_SUCCESS;
		}
		int ret = sendto(sockfd,buf,strlen(buf)+1,0,(SP)&srv_addr,addrlen);
		if(0 >= ret)
		{
			printf("网络异常!\n");
			close(sockfd);
			return EXIT_FAILURE;
		}
		//	接收数据和对方的地址
		ret = recvfrom(sockfd,buf,buf_size,0,(SP)&srv_addr,&addrlen);
		if(0 >= ret)
		{
			printf("网络异常,通信结束!");
			close(sockfd);
			return EXIT_FAILURE;
		}
		printf("from %s recv:[%s] bits:%d\n",
			inet_ntoa(srv_addr.sin_addr),buf,ret);

	}
}	

?

  网络协议 最新文章
使用Easyswoole 搭建简单的Websoket服务
常见的数据通信方式有哪些?
Openssl 1024bit RSA算法---公私钥获取和处
HTTPS协议的密钥交换流程
《小白WEB安全入门》03. 漏洞篇
HttpRunner4.x 安装与使用
2021-07-04
手写RPC学习笔记
K8S高可用版本部署
mySQL计算IP地址范围
上一篇文章      下一篇文章      查看所有文章
加:2022-10-17 13:08:02  更:2022-10-17 13:09:03 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/25 21:38:52-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码