如何提高linux socket服务器的并发数和性能?

幸福淡藍色 2013-09-22 09:48:32
最近在写socket服务器,用的多线程并发,但是并发数太少了,想用epoll 的,但是epoll接收数据容易出错!
...全文
391 10 打赏 收藏 转发到动态 举报
写回复
用AI写文章
10 条回复
切换为时间正序
请发表友善的回复…
发表回复
幸福淡藍色 2013-10-09
  • 打赏
  • 举报
回复
答非所问啊!!
qq120848369 2013-09-28
  • 打赏
  • 举报
回复
代码有bug就找出来,实际开发是不会写裸socket的,需要先开发网络事件库,方便开发抽象。
fdl19881 2013-09-28
  • 打赏
  • 举报
回复
如果是想开发公司的项目等,就用现成的开源网络库, 如果只是想学学,那你就找下自己的BUG
幸福淡藍色 2013-09-27
  • 打赏
  • 举报
回复
就是找不到错误才来这里面求助嘛!
幸福淡藍色 2013-09-27
  • 打赏
  • 举报
回复

#include "test.h"


int iEpollfd = 0;
struct epoll_event Epoll_ev;
struct epoll_event Epoll_events[EPOLLMAXNUM];

int main()
{
	int iRetvalue = 0;


	while(TRUE)
	{
		iRetvalue = server_init(); 
		if(0 > iRetvalue)
		{
			sleep(3);
		}

		continue;
	}
	

	return 0;
}

static int server_init()
{
	int iRetvalue = 0;
	int iServerfd = 0;
	int iClientfd = 0;
	int iRetfds   = 0;
	int i;
	char recvbuf[1024] = "\0";

	struct sockaddr_in Clientaddr;
	socklen_t socklen = sizeof(struct sockaddr_in);
	memset(&Clientaddr, 0, sizeof(Clientaddr));

	iServerfd = socket_init();
	if(0 > iServerfd)
	{
		printf("socket init error\n");
		return -1;
	}

	int iCount = 0;

	while(TRUE)
	{
		iRetfds = epoll_wait(iEpollfd, Epoll_events, EPOLLMAXNUM, 0);
		for(i = 0; i < iRetfds; i++)
		{
			if(0 > (iClientfd == Epoll_events[i].data.fd)) continue;
			if(iServerfd == Epoll_events[i].data.fd)
			{
				iClientfd = accept(iServerfd, (struct sockaddr*)&Clientaddr, &socklen);
				if(0 > iClientfd)
				{
					iRetvalue = errno;
					printf("[%s][%s][%d]:accept error:%s\n", __FILE__, __func__, __LINE__, strerror(errno));
					break;
				}
				printf("客户端[ %d ]连接成功\n", iClientfd);

				socket_setnonblock(iClientfd);    

				Epoll_ev.data.fd = iClientfd;                            //设置与处理事件相关的描述符
				Epoll_ev.events  = EPOLLIN|EPOLLET;                              //设置要处理的事件类型
				epoll_ctl(iEpollfd, EPOLL_CTL_ADD, iClientfd, &Epoll_ev);  //注册epoll事件

				continue;
			}//end if

			if(Epoll_events[i].events&EPOLLIN)
			{
				iClientfd = Epoll_events[i].data.fd;
				//printf("iClientfd = %d\n", Epoll_events[i].data.fd);
				int iTotallen = 0;
				int iOnce = 0;
				do
				{
					/*
					iOnce = recv(iClientfd, &iTotallen, 4, 0);
					if(4 != iOnce)
					{
						printf("接收长度错误!\n");
						break;
					}
					printf("------------长度: %d\n", iTotallen);
*/
					memset(&recvbuf, 0, sizeof(recvbuf));
					//iOnce = recv(iClientfd, recvbuf, iTotallen, 0);
					iOnce = recv(iClientfd, recvbuf, 1024, 0);
					if(iOnce != 621)
					{
						printf("接收错误");
						break;
					}

					//printf("%s:socket:%d\n",recvbuf,iClientfd);
					iCount++;
					printf("iCount = %d\n", iCount);
				}
				while(0);

				Epoll_ev.data.fd = iClientfd;                            //设置与处理事件相关的描述符
				Epoll_ev.events  = EPOLLIN|EPOLLET;                       //设置要处理的事件类型
				epoll_ctl(iEpollfd, EPOLL_CTL_ADD, iClientfd, &Epoll_ev);  //注册epoll事件
			}// end if
		}//end for
	}//end while

	close(iServerfd);
	return 0;
}


static int socket_init()
{
	int iRetvalue = 0;

	int iSockfd = 0;
	struct sockaddr_in Serveraddr;
	socklen_t socklen = sizeof(struct sockaddr_in);

	memset(&Serveraddr, 0, sizeof(Serveraddr));
	Serveraddr.sin_family = AF_INET;
	Serveraddr.sin_port   = htons(SERVER_PORT);
	Serveraddr.sin_addr.s_addr = htonl(SERVER_ADDR); 

	iSockfd = socket(AF_INET, SOCK_STREAM, 0);
	if(0 > iSockfd)
	{
		printf("create socket error\n");
		return -1;
	}

	iEpollfd = epoll_create(EPOLLMAXNUM);
	if(0 > iEpollfd)
	{
		printf("create epoll error\n");
		close(iSockfd);
		return -1;
	}

	Epoll_ev.data.fd = iSockfd;                            //设置与处理事件相关的描述符
	Epoll_ev.events  = EPOLLIN|EPOLLET;                              //设置要处理的事件类型
	epoll_ctl(iEpollfd, EPOLL_CTL_ADD, iSockfd, &Epoll_ev);  //注册epoll事件


	iRetvalue = socket_setnonblock(iSockfd);       //把socket设置为非阻塞,epoll的边缘出发模式需要。
	if(iRetvalue)
	{
		printf("[%s][%s][%d]:设置非阻塞模式失败%s\n", __FILE__, __func__, __LINE__, strerror(errno));
		close(iSockfd);
		return -1;
	}

	iRetvalue = bind(iSockfd, (struct sockaddr *)&Serveraddr, socklen);
	if(iRetvalue)
	{
		printf("[%s][%s][%d]:bind error: %s\n", __FILE__, __func__, __LINE__, strerror(errno));
		close(iSockfd);
		return -1;
	}

	iRetvalue = listen(iSockfd, LISTENQ);
	if(iRetvalue)
	{
		printf("[%s][%s][%d]:listen error: %s\n", __FILE__, __func__, __LINE__, strerror(errno));
		close(iSockfd);
		return -1;
	}

	printf("监听socket成功 : %d\n", iSockfd);
	printf("请耐心等待连接.......\n");

	return iSockfd;
}

static int socket_setnonblock(int iSockfd)
{
	int iOpts = fcntl(iSockfd, F_GETFL);  //得到原有的句柄属性
	if(iOpts < 0)
	{
#ifdef PRINT
		printf("[%s][%s][%d]:fcntl error: %s\n", __FILE__, __func__, __LINE__, strerror(errno));
#endif
		return -1;
	}

	iOpts = iOpts|O_NONBLOCK;             //在原有属性的基础上添加非阻塞属性
	if(fcntl(iSockfd, F_SETFL, iOpts)<0)
	{
#ifdef PRINT
		printf("[%s][%s][%d]: fcntl error: %s\n", __FILE__, __func__, __LINE__, strerror(errno));
#endif
		return -1;
	}

	return 0;
}




qgw_2000 2013-09-27
  • 打赏
  • 举报
回复
推荐使用libevent或者libev。
hello_wcy 2013-09-22
  • 打赏
  • 举报
回复
对啊 ,大并发一般用epoll的,如果不是大量的并发,用select效率差不多
choose_one 2013-09-22
  • 打赏
  • 举报
回复
最好简单贴下代码,不然没法帮你
Carl_CCC 2013-09-22
  • 打赏
  • 举报
回复
你查查为什么epoll出错,大并发,一般都是用epoll的。肯定用不了多线程。
qq120848369 2013-09-22
  • 打赏
  • 举报
回复
有bug的程序当然会出错了,楼主脑子里在想什么。

23,121

社区成员

发帖
与我相关
我的任务
社区描述
Linux/Unix社区 应用程序开发区
社区管理员
  • 应用程序开发区社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧