网络编程(二)广播、组播、点播

相关接口函数:https://www.cnblogs.com/wanghuaijun/p/6021711.html

不自己写了,在这里面找吧!!!  我这里就写事例代码

一、几种服务器 IO 模型简介

1、阻塞型------->通过多线程或者多进程进行网络通信

2、非阻塞型------------->通过轮询方式进行网络通信

3、多路复用型-------->通过 select 函数设置通信属性实现

4、信号(UDP)

说明:以下事例均实现通信功能,即通过服务器转发来自客户端的信息

二、简单说一下个人对网络通信的理解

        对于网络通信当中的 UDP 和 TCP 通信,UDP 通信适用于小规模通信,因为如果每个人的消息发送都是由自己完成,那么将占用大量的客户端资源,当然 UDP 相对TCP 来说比较简单。而 TCP 通信最核心的内容就是转发,将发送的任务交给服务器,信息先通过网络发送给服务器,然后再由服务器转发。这样用户只需要和服务器进行通信,而不是直接与客户端通信,那么由服务器提供通信资源,这样客户端资源就没有那么大的消耗。

三、先写多路复用的事例代码(用的数组实现,你可以尝试使用内核链表实现

内核链表实现以下功能相关源码自行在该页面下载https://download.csdn.net/download/qq_41985711/10680665
3.1、客户端

// 客户端, 消息发送

#include "myhead.h"

 
void useage(int argc, char **argv)
{
	if (argc != 3)
	{
		printf("use: %s IP PORT\n", argv[0]);
		exit(0);
	}
 
}
 
int main(int argc, char **argv)   
{
	useage(argc, argv);
 
	// 一、创建套接字,获取描述符 fd
	int fd = socket(AF_INET, SOCK_STREAM, 0);
 
	// 二、设置服务器(也就是接收端)的网络属性
	struct sockaddr_in seraddr;
	socklen_t serlen = sizeof(seraddr);
	bzero(&seraddr, serlen);
 
	seraddr.sin_family = AF_INET;
	seraddr.sin_addr.s_addr = inet_addr(argv[1]);
	seraddr.sin_port = htons(atoi(argv[2]));
 
	// 三、连接服务器
	int ret = connect(fd, (struct sockaddr *)&seraddr, serlen);
	if (ret == -1)
	{
		perror("connect filed: \n");
		return -1;
	}

	char msg[100];
	// 四、准备 select 参数
	fd_set rset;
	while (1)
	{
		FD_ZERO(&rset);
		FD_SET(0, &rset);
		FD_SET(fd, &rset);
        

        // select 函数查吧!这里告诉功能
        // 监控文件描述符的状态改变
		ret = select(fd+1, &rset, NULL, NULL, NULL);

	    // 五、被监控文件描述符发生状态改变
		if (ret > 0)
		{
			if (FD_ISSET(0, &rset))
			{
				bzero(msg, 100);
				scanf("%s", msg);
				ret = send(fd, msg, 100, 0);
				printf("sent %d bytes\n", ret);
			}
			else if (FD_ISSET(fd, &rset))
			{
				bzero(msg, 100);
				ret = recv(fd, msg, 100, 0);
				if (ret <= 0)
				{
					if (ret == 0)
						printf("server quit!!!\n");
					else 
						printf("recv failed!!!\n");
					close(fd);
					return 0;
				}
				printf("rerv msg %d bytes---->%s\n", ret, msg);
			}

		}
		else if (ret == -1)
		{
			perror("select filed: \n");
			return -1;
		}
		else if(ret == 0)
		{
			printf("delay time\n");
			return -1;
		}
	}

	close(fd);
 
	return 0;
}

3.2、服务器

// tcp select 广播 接收端

#include "myhead.h"
 
void useage(int argc, char **argv)
{
	if (argc != 2)
	{
		printf("use: %s <PORT>\n", argv[0]);
		exit(0);
	}
}
 
 
int main(int argc, char **argv)
{
	useage(argc, argv);
 
	// 一、创建套接字 socket,获取描述符 fd
	int fd = socket(AF_INET, SOCK_STREAM, 0);
 
	// 二、设置服务器网络属性(未绑定)-->(端口号,IP)---->struct sockaddr_in
	struct sockaddr_in seraddr;
	socklen_t len = sizeof (seraddr);
	bzero(&seraddr, len);
 
	seraddr.sin_family = AF_INET;
	seraddr.sin_addr.s_addr = htonl(INADDR_ANY);
	seraddr.sin_port = htons(atoi(argv[1]));
 
	// 三、绑定服务器属性
	bind(fd, (struct sockaddr *)&seraddr, len);
 
	// 四、设置监听模式(最多可同时接收来自 N+4 客户端的信息),
	listen(fd, 3);
 
	// 五、等待客户端信息,并保存客户端网络属性(不想保存就写 NULL)
	int n = 0;
	printf("please input how many ports join?\n");
	scanf("%d", &n);
	struct sockaddr_in cliaddr[n];
	socklen_t clilen = sizeof (struct sockaddr_in);
	int connfd[n];
	bzero(connfd, sizeof (connfd));
 

	// 六、将连接的客户端的套接字保存
	fd_set rset;
	char msg[100];
	int ret;
	int i = 0;
	int j = 0;
	int maxfd  = fd;
	int k;

	while (1)
	{
	// 七、将需要监控的套接字加入就绪集合
	 	FD_ZERO(&rset);
		FD_SET(fd, &rset);
		for (j = 0; j < i; j++)
		{
			if (connfd[j] == -1)
				continue;
			FD_SET(connfd[j], &rset);
		}
		ret = select(maxfd+1, &rset, NULL, NULL, NULL);
		if (ret > 0)
		{
			if (FD_ISSET(fd, &rset))
			{
				connfd[i] = accept(fd, (struct sockaddr *)&cliaddr[i], &clilen);
				if (connfd[i] == -1)
				{
					perror("accept filed: ");
					continue;
				}
				printf("from client ip: %s   port: %hu\n", 
											inet_ntoa(cliaddr[i].sin_addr), ntohs(cliaddr[i].sin_port));
				maxfd = connfd[i] < maxfd ? maxfd : connfd[i];
				i++;
				continue;

			}
			for (j = 0; j <= i; j++)
			{
				if (FD_ISSET(connfd[j], &rset))
				{
					bzero(msg, 100);
					ret = recv(connfd[j], msg, 100, 0);
					// 判断是数据还是断开连接
					if (ret <= 0)
					{
						if (ret == 0)
							printf("socket %d quit!!!\n", connfd[j]);
						else
							printf("recv failed!!!\n");

						close(connfd[j]);
						connfd[j] = -1;

						continue;
					}
					else if (ret > 0)
					{
						for (k = 0; k < i; k++)
						{
							if (k == j)
								continue;
							if (connfd[k] == -1)
								continue;
							send(connfd[k], msg, 100, 0);
						}		
					}
					
				}
			}

		}
		else if (ret == 0)
		{
			printf("delay time\n");
			return -1;
		}
		else if (ret == -1)
		{
			perror("select filed: ");
			return -1;
		}

	}
	
	close(fd);
	return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_41985711/article/details/82751858
今日推荐