unix网络编程之利用select 实现群发的功能

首先 运行在linux 运行gcc -g -o select select.c
/ *******select.c*********/
/ *******Using select() for I/O multiplexing */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
/* port we're listening on */
#define PORT 2020

int main(int argc, char *argv[])
{
	/*定义描述符集合 */
	fd_set master;
	/* 定义select函数可读的描述符*/
	fd_set read_fds;
	/* 服务器地址 */
	struct sockaddr_in serveraddr;
	/* 客户地址 */
	struct sockaddr_in clientaddr;
	/* 定义最大描述符数 */
	int fdmax;
	/* 监听描述符 */
	int listener;
	/* accept描述符 */
	int newfd;
	/* 缓冲 */
	char buf[1024];
	int nbytes;
	/* 设置 setsockopt() SO_REUSEADDR */
	int yes = 1;
	int addrlen;
	int i, j;
	/* 清除 */
	FD_ZERO(&master);
	FD_ZERO(&read_fds);

	/* 连接 */
	if((listener = socket(AF_INET, SOCK_STREAM, 0)) == -1)
	{
		perror("Server-socket() error lol!");

		exit(1);
	}
	printf("Server-socket() is OK...\n");
	/*判断地址以用 */
	if(setsockopt(listener, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1)
	{
		perror("Server-setsockopt() error lol!");
		exit(1);
	}
	printf("Server-setsockopt() is OK...\n");

	/* bind */
	serveraddr.sin_family = AF_INET;
	serveraddr.sin_addr.s_addr = INADDR_ANY;
	serveraddr.sin_port = htons(PORT);
	memset(&(serveraddr.sin_zero), '\0', 8);

	if(bind(listener, (struct sockaddr *)&serveraddr, sizeof(serveraddr)) == -1)
	{
		perror("Server-bind() error lol!");
		exit(1);
	}
	printf("Server-bind() is OK...\n");

	/* listen */
	if(listen(listener, 10) == -1)
	{
		perror("Server-listen() error lol!");
		exit(1);
	}
	printf("Server-listen() is OK...\n");

	/* 把 listener 加到 master set */
	FD_SET(listener, &master);

	/* keep track of the biggest file descriptor */
	fdmax = listener; /* so far, it's this one*/

	/* 循环了 */
	for(;;)
	{
		/* copy it */
		read_fds = master;

		if(select(fdmax+1, &read_fds, NULL, NULL, NULL) == -1)
		{
			perror("Server-select() error lol!");
			exit(1);
		}
		printf("Server-select() is OK...\n");

		/*从存在的描述符中查找要读的数据*/
		for(i = 0; i <= fdmax; i++)
		{
			if(FD_ISSET(i, &read_fds))
			{ /* 得到一个... */
				if(i == listener)
				{
					/* h处理这个的连接 */
					addrlen = sizeof(clientaddr);
					if((newfd = accept(listener, (struct sockaddr *)&clientaddr, &addrlen)) == -1)
					{
						perror("Server-accept() error lol!");
					}
					else
					{
						printf("Server-accept() is OK...\n");

						FD_SET(newfd, &master); /* add to master set */
						if(newfd > fdmax)
						{ /* keep track of the maximum */
							fdmax = newfd;
						}
						printf("%s: New connection from %s on socket %d\n", argv[0], inet_ntoa(clientaddr.sin_addr), newfd);
					}
				}
				else
				{
					/* 处理从客户端来的数据*/
					if((nbytes = recv(i, buf, sizeof(buf), 0)) <= 0)
					{
						/* 没有数据 */
						if(nbytes == 0)
							/* 断开连接。 */
							printf("%s: socket %d hung up\n", argv[0], i);

						else
							perror("recv() error lol!");

						/* 关闭... */
						close(i);
						/* 删除这个连接符 */
						FD_CLR(i, &master);
					}
					else
					{
						/* we got some data from a client*/
						for(j = 0; j <= fdmax; j++)
						{
							/* 发给每个人! */
							if(FD_ISSET(j, &master))
							{
								/* 除了监听的和自己的。 */
								if(j != listener && j != i)
								{
									if(send(j, buf, nbytes, 0) == -1)
										perror("send() error lol!");
								}
							}
						}
					}
				}
			}
		}
	}
	return 0;
}


然后在运行 ./select & 或者ctrl+z 让他后台运行
开一个窗口 运行telnet localhostip 2020 
程序如下

更多文章,欢迎访问http://blog.csdn.net/wallwind 转载请注明出处

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值