网络通信(基于TCP/IP实现客户端/服务器的通信)
创始人
2024-09-25 01:25:27
0

编程结构

被连接者需要完成的任务(服务端):
1、创建socket内核对象,内核创建完成后会返回它的描述符(该描述只是为了完成连接,三次握手)
2、准备本机地址(ip地址+端口号)
3、绑定(把本机地址与socket对象进行绑定)
4、开启监听,并设置排队的队列长度
5、等待连接,连接成功后,内核会再返回一个连接成功的Socket描述符,专门用来通信
for(;;)
{
    6、接收请求
    7、返回结果
}
8、关闭通信的Socket对象
9、关闭连接的Socket对象

连接者需要完成的任务(客户端):
1、创建socket内核对象,内核创建完成后会返回它的描述符
2、准备被连接者的地址(ip地址+端口号)
3、发起连接,使用Socket+地址(ip地址+端口号)发起连接请求
for(;;)
{
    4、发送请求
    5、接收结果
}
6、关闭Socket对象

相关函数

int socket(int domain, int type, int protocol);
功能:创建Socket对象
domain:
    AF_UNIX, AF_LOCAL   采用本地socket文件进行通信,如果用它则只能本机上的两个进程进行通信
    AF_INET             IPv4地址
    AF_INET6               IPv6地址
type:
    SOCK_STREAM    数据流    TCP
    SOCK_DGRAM 报文 UDP
protocol:
    特殊通信协议,写0即可
返回值:
    成功则返回Socket对象描述符,失败返回-1。

// 基本地址类型,它是socket系列接口的表面参数,而实际使用的是sockaddr_un或sockaddr_in,我们需要把sockaddr_in强制转换成sockaddr类型。
struct sockaddr_in 
{
    sa_family_t sin_family;        // 地址类型,与domain保持一致即可
    in_port_t sin_port;            // 端口号,网络字节序的2字节整数
    struct in_addr sin_addr.s_addr;    // IP地址,网络字节序的4字节整数
};

int bind(int sockfd, const struct sockaddr *addr,socklen_t addrlen);
功能:绑定Socket对象与通信地址
sockfd:Socket对象描述符
addr:通信地址,实际提供可能是sockaddr_un或sockaddr_in,需要对它们进行强制转换
addrlen:addr结构体的字节数
返回值:成功返回0,失败返回-1
    
int listen(int sockfd, int backlog);
功能:开启Socket对象的监听
sockfd:Socket地址描述符
backlog:备胎的数量
    
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
功能:等待连接,没有成功连接之前,会进入阻塞状态
sockfd:Socket对象描述符
addr:用于存储连接者的通信地址
addrlen:
    既是输入(告诉accetp接口,addr结构体的字节数),也是输出(实际接收到的addr结构的字节数)
返回值:建立连接的,能够通信的Socket对象描述符,失败返回-1
    
int connect(int sockfd, const struct sockaddr *addr,socklen_t addrlen);
功能:让sockfd对象向addr地址发起连接
sockfd:Socket对象描述符
addr:连接目标的地址
addrlen:addr结构体的字节数
返回值:成功返回0,失败返回-1
    
ssize_t recv(int sockfd, void *buf, size_t len, int flags);
功能:从Socket对象读接收干字节
sockfd:Socket对象描述符
buf:接收数据的内存块首地址
len:buf的字节数
flags:是否阻塞,写0即可
返回值:成功接收到了多少个字节,失败返回-1
    
ssize_t send(int sockfd, const void *buf, size_t len, int flags);
功能:通过Socket对象发送若干字节
sockfd:Socket对象描述符
buf:要发送的内存块首地址
len:要发送的字节数
flags:是否阻塞,写0即可
返回值:成功发送了多少个字节,失败返回-1
    
int close(int fd);
功能:关闭fd描述所代表的内核对象
    
uint16_t htons(uint16_t hostshort);
功能:把本地字节序的 unsigned short 类型的数据转换网络字节序
    
in_addr_t inet_addr(const char *cp);
功能:把字符串格式 点分十进制的ip地址 转换成网络字节序的4字节ip地址

代码:

服务端:
#include  #include  #include  #include  #include  #include  #include   int main(int argc,const char* argv[]) { 	// 创建socket对象 	int server_fd = socket(AF_INET,SOCK_STREAM,0); 	if(0 > server_fd) 	{ 		perror("socket"); 		return -1; 	}  	// 准备本机地址 	struct sockaddr_in addr; 	addr.sin_family = AF_INET; 	addr.sin_port = htons(2233); 	addr.sin_addr.s_addr = inet_addr("10.0.2.15"); 	socklen_t addrlen = sizeof(addr);  	// 绑定socket对象和地址	 	if(bind(server_fd,(struct sockaddr*)&addr,addrlen)) 	{ 		perror("bind"); 		return -2; 	}  	// 开启监听 	if(listen(server_fd,6)) 	{ 		perror("listen"); 		return -3; 	}  	// 等待连接 	int sockfd = accept(server_fd,(struct sockaddr*)&addr,&addrlen); 	if(0 > sockfd) 	{ 		perror("accept"); 		return -4; 	}  	char buf[BUFSIZ]; 	for(;;) 	{ 		// 接收数据 		int ret = read(sockfd,buf,BUFSIZ); 		if(0 >= ret || !strcmp("quit",buf)) 			break;  		printf("recv:%s byte:%d\n",buf,ret);  		strcat(buf,",return!");  		// 返回数据 		ret = write(sockfd,buf,strlen(buf)+1); 		if(0 >= ret) 			break; 	} 	 	printf("通信结束!\n");  	// 关闭负责通信的socket对象 	close(sockfd); 	// 关闭负责连接的socket对象 	close(server_fd); 	return 0; }
客户端:
#include  #include  #include  #include  #include  #include  #include   int main(int argc,const char* argv[]) { 	// 创建socket对象 	int sockfd = socket(AF_INET,SOCK_STREAM,0); 	if(0 > sockfd) 	{ 		perror("socket"); 		return -1; 	}  	// 准备服务端的地址 	struct sockaddr_in addr; 	addr.sin_family = AF_INET; 	addr.sin_port = htons(2233); 	addr.sin_addr.s_addr = inet_addr("10.0.2.15"); 	socklen_t addrlen = sizeof(addr);  	// 连接 	if(connect(sockfd,(struct sockaddr*)&addr,addrlen)) 	{ 		perror("connect"); 		return -2; 	}  	char buf[BUFSIZ]; 	for(;;) 	{ 		printf(">>>"); 		scanf("%s",buf);  		// 发送数据 		int ret = write(sockfd,buf,strlen(buf)+1); 		if(0 >= ret || !strcmp("quit",buf)) 			break;  		// 接收数据 		ret = read(sockfd,buf,BUFSIZ); 		if(0 >= ret) 			break;  		printf("recv:%s byte:%d\n",buf,ret); 	}	 	printf("通信结束!\n");  	// 关闭socket对象 	close(sockfd); 	 	return 0; }

相关内容

热门资讯

黑科技辅助(德州之星外挂)外挂... 黑科技辅助(德州之星外挂)外挂透视辅助挂(透视)一贯真的是有挂(黑科技脚本)-哔哩哔哩;1、德州之星...
黑科技系统(wepoke透视该... 黑科技系统(wepoke透视该购买渠道)外挂黑科技辅助方法(透视)原来是真的有挂(黑科技详情)-哔哩...
黑科技辅助(红龙扑克是不是有问... 黑科技辅助(红龙扑克是不是有问题)外挂透明挂辅助软件(透视)总是真的有挂(黑科技教程)-哔哩哔哩小薇...
黑科技中牌率(wepoke模拟... 黑科技中牌率(wepoke模拟器)外挂黑科技辅助下载(透视)果然真的有挂(黑科技工具)-哔哩哔哩1、...
黑科技插件(微扑克透牌软件)外... 黑科技插件(微扑克透牌软件)外挂黑科技辅助神器(透视)竟然有挂(黑科技辅助)-哔哩哔哩1、微扑克透牌...
黑科技app(微扑克有辅助透视... 黑科技app(微扑克有辅助透视)外挂黑科技辅助助手(透视)一直存在有挂(黑科技脚本)-哔哩哔哩1、用...
黑科技辅助挂(wpk辅助外挂)... 黑科技辅助挂(wpk辅助外挂)外挂黑科技辅助技巧(透视)原来真的有挂(黑科技插件)-哔哩哔哩1、完成...
黑科技app(wpk ai机器... 黑科技app(wpk ai机器人)外挂黑科技辅助教程(透视)都是存在有挂(黑科技揭秘)-哔哩哔哩;1...
黑科技好牌(智星德州菠萝有挂吗... 黑科技好牌(智星德州菠萝有挂吗)外挂透视辅助下载(透视)果然存在有挂(黑科技规律)-哔哩哔哩1、智星...
黑科技辅助挂(智星德州菠萝怎么... 黑科技辅助挂(智星德州菠萝怎么看有没有开挂)外挂透明挂辅助助手(透视)原来有挂(黑科技攻略)-哔哩哔...