LINUX--select服务器群发和回射

本文档展示了如何在Linux环境下利用select函数处理多个套接字连接,实现服务器对客户端消息的接收、回射以及群发功能。通过创建socket、设置套接字选项、监听和接受连接,使用select进行文件描述符管理,实现并发通信。当有新客户端连接时,将其加入管理集合,并在接收到消息后广播给所有在线客户端。
摘要由CSDN通过智能技术生成

LINUX–select服务器群发和回射

#服务器
select()函数 控制文件描述符

#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <string.h>
#include <signal.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <sys/select.h>
#include
#include
using namespace std;

vector vfds;
vector::iterator it;

typedef struct chat
{
char name[16] = { 0 };
char text[1024] = { 0 };

}CHAT_T;

int main()
{
int socket_fd = socket(AF_INET, SOCK_STREAM, 0);
if (socket_fd == -1)
{
perror(“socket:”);

}
struct sockaddr_in ser_add;
ser_add.sin_family = AF_INET;//ipv4
ser_add.sin_port = htons(8099);//转换为网络字节序
//inet_aton("146.56.129.60", &ser_add.sin_addr.s_addr);
ser_add.sin_addr.s_addr = htonl(INADDR_ANY);//对接本地任意的空闲ip
//ser_add.sin_addr.s_addr = htonl();//对接本地任意的空闲ip146.56.129.60 
 // 设置套接字选项避免地址使用错误  
int on = 1;
if ((setsockopt(socket_fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on))) < 0)
{
	perror("setsockopt failed");
	exit(EXIT_FAILURE);
}

int ret = bind(socket_fd, (struct sockaddr*)&ser_add, sizeof(ser_add));
if (ret == -1)
{
	perror("bind:");

}
ret = listen(socket_fd, SOMAXCONN);
if (ret == -1)
{
	perror("listen:");

}

char buff[1024] = { 0 };

fd_set set;//集合
fd_set allset;//集合
FD_SET(socket_fd,&allset);
int maxfd = socket_fd;


while (1)
{
	set = allset;//做备份
	cout << "wait for slect..." << endl;
	int nres = select(maxfd+1,&set,NULL,NULL,NULL);//管理fd
	cout << "slect is return :" <<nres<< endl;
	//select 返回有两种情况
	if (FD_ISSET(socket_fd,&set)) 
	{
		struct sockaddr_in cli_add;
		socklen_t addrlen = sizeof(cli_add);
		int con_fd = accept(socket_fd, (struct sockaddr*)&cli_add, &addrlen);
		vfds.push_back(con_fd);
		cout << "current vfds:" << vfds.size() << endl;
		cout << "someone online" << "con_fd:" << con_fd << endl;
		//把新的客户端的fd交给select来管理
		FD_SET(con_fd, &allset);
		if (con_fd>maxfd) 
		{
			maxfd = con_fd;
		}

	
	}
	else 
	{
		for (it=vfds.begin();it!=vfds.end();it++) 
		{
		
			if (FD_ISSET(*it,&set))
			{
				int r_size=read(*it, (CHAT_T*)buff, sizeof(CHAT_T));
				if (r_size==0) //有客户端断开
				{
					cout << "one client esc:" <<*it<< endl;
					//把客户端从集合里删除
					FD_CLR(*it, &allset);
					vfds.erase(it);//vecor 删除
					break;

				}
				printf("%ssay:%s", ((CHAT_T*)buff)->name, ((CHAT_T*)buff)->text);
				//cout << "accept buff=" << ((CHAT_T*)buff)->name <<((CHAT_T*)buff)->text<<endl;
				//write(*it, buff, r_size);//回射
				//群发动作
				for (it = vfds.begin(); it != vfds.end(); it++)
				{
					write(*it, (CHAT_T*)buff, r_size);
				
				}
				bzero(buff,sizeof(buff));
				break;
			}

		}
		
		
	}
	
	
	


}






return 0;

}

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值