[置顶] 搭建一个后台服务器--服务端代码(异步,大并发)

#include <stdio.h>
#include <time.h>
#include <fcntl.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>

#ifndef WIN32
#include <unistd.h>
#include <sys/epoll.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#else
#include <WinSock2.h>
#define close( f ) closesocket( f )
#endif

struct my_event_s
{
	int fd;
	char recv[64];
	char send[64];

	int rc_pos;
	int sd_pos;
};

int main( int argc, char** argv )
{
	int port;
	int flag;
	int size;
	int sock_server;
	int sock_client;
	time_t current;
	time_t last;
	int num;
	int e_num;
	int my_empty_index;
	int i,j;
	int event_flag;
#define EPOLL_MAX 51200
	struct epoll_event wait_events[ EPOLL_MAX ];
	struct my_event_s my_event[ EPOLL_MAX ];
	struct my_event_s* tobe_myevent;
	struct epoll_event tobe_event;
	int epfd;

#define RECV_BUF_LEN 256
	char buffer[ RECV_BUF_LEN ];

	struct sockaddr_in addr_server;
	struct sockaddr_in addr_client;

	if( argc <= 1 )
	{
		printf( "please set your port\n" );
		return 0;
	}

	printf( "your port:%s\n", argv[1] );

#ifdef WIN32
		WSADATA wsadata;
		flag = WSAStartup( 0x101, &wsadata );
		if( flag )
		{
			printf( "your windows socket setup wrong\n" );
			return 0;
		}

#endif

	port = atoi(argv[1]);
	
	addr_server.sin_family = AF_INET;
	addr_server.sin_port = htons( port );
	addr_server.sin_addr.s_addr = htonl( INADDR_ANY );



	sock_server = socket( AF_INET, SOCK_STREAM, 0 );
	flag = fcntl( sock_server, F_GETFL, 0 );
	fcntl( sock_server, F_SETFL, flag | O_NONBLOCK );

	flag = bind( sock_server, ( struct sockaddr* )&addr_server, sizeof( struct sockaddr ) );
	if( flag < 0 )
	{
		printf( "your bind is not ok\n" );
		close( sock_server );
		return 0;
	}

	flag = listen( sock_server, 1024 );
	if( flag < 0 )
	{
		printf( "your listen is not ok\n");
		close( sock_server );
		return 0;
	}

	
	epfd = epoll_create( EPOLL_MAX );
	if( epfd <= 0 )
	{
		printf( "event module could not be setup\n");
		close( sock_server );
		return 0;
	}

	tobe_event.events = EPOLLIN;
	tobe_event.data.fd = sock_server;

	epoll_ctl( epfd,  EPOLL_CTL_ADD, sock_server,  &tobe_event );


	size = sizeof( addr_client );
	num = 0;
	last = 0;
	my_empty_index = 0;

	while(1)
	{
#define WAIT_TIME_OUT 600
		e_num = epoll_wait( epfd, wait_events, EPOLL_MAX, WAIT_TIME_OUT );
		if( e_num <= 0 )
		{
			continue;
		}

		for( i = 0; i < e_num; ++i )
		{
			if( sock_server == wait_events[ i ].data.fd )
			{
				while(1)
				{
					sock_client = accept( sock_server, ( struct sockaddr* )&addr_client, ( socklen_t*)&size );
					if( sock_client < 0 )
					{
						if( errno == EAGAIN )
						{
							break;
						}
						if( errno == EINTR )
						{
							continue;
						}
						break;
					}

					tobe_myevent = my_event + my_empty_index;
					memset( tobe_myevent, 0, sizeof( struct my_event_s ) );
					tobe_myevent->fd = sock_client;

					flag = fcntl( sock_client, F_GETFL, 0 );
					fcntl( sock_client, F_SETFL, flag | O_NONBLOCK );

					tobe_event.events = EPOLLIN | EPOLLET;
					tobe_event.data.u32 = my_empty_index;

					epoll_ctl( epfd, EPOLL_CTL_ADD, sock_client, &tobe_event );

					
					for( j = my_empty_index + 1; j < EPOLL_MAX; ++j )
					{
						if( !my_event[ j ].fd )
						{
							my_empty_index = j;
							break;
						}
					}
					
					if( my_event[j].fd )
					{
						for( j = 0; j < EPOLL_MAX; ++j )
						{
							if( !my_event[ j ].fd )
							{
								my_empty_index = j;
								break;
							}
						}

						if( my_event[ j ].fd )
						{
							printf( "your events has been none else\n");
							close( sock_client );
							close( sock_server );
							return 0;
						}
					}

					++num;
					current = time( 0 );
					if( current > last )
					{
						printf( "last sec qps:%d\n", num );
						num = 0;
						last = current;
					}

					memcpy( tobe_myevent->send, ¤t, sizeof(time_t) );
					
					flag = recv( sock_client, tobe_myevent->recv, 64, 0 );
					if( flag < 64 )
					{
						if( flag > 0 )
							tobe_myevent->rc_pos += flag;
						continue;
					}

					if( tobe_myevent->recv[31] || tobe_myevent->recv[63] )
					{
						printf( "your recv does follow the protocal\n");
						tobe_myevent->fd = 0;
						close( sock_client );
						continue;
					}
					

					flag = send( sock_client, tobe_myevent->send, sizeof( time_t ), 0 );
					if( flag < sizeof( time_t ) )
					{
						tobe_event.events =  EPOLLET | EPOLLOUT;
						epoll_ctl( epfd, EPOLL_CTL_MOD, sock_client, &tobe_event );
						if( flag > 0 )
							tobe_myevent->sd_pos += flag;
						continue;
					}
					tobe_myevent->fd = 0;
					close( sock_client );

				}
				
			}
			else
			{
				tobe_myevent = my_event + wait_events[ i ].data.u32;
				sock_client = tobe_myevent->fd;
				event_flag = wait_events[ i ].events;

				if( event_flag & EPOLLHUP )
				{
					tobe_myevent->fd = 0;
					close( sock_client );
					continue;
				}
				else if( event_flag & EPOLLERR )
				{
					tobe_myevent->fd = 0;
					close( sock_client );
					continue;
				}
				else if( event_flag & EPOLLOUT )
				{
					if( tobe_myevent->rc_pos != 64 )
					{
						continue;
					}

					if( tobe_myevent->sd_pos >= sizeof( time_t ) )
					{
						tobe_myevent->fd = 0;
						close( sock_client );
						continue;
					}

					flag = send( sock_client, tobe_myevent->send + tobe_myevent->sd_pos, sizeof( time_t ) - tobe_myevent->sd_pos, 0 );
					if( flag < 0 )
					{
						if( errno == EAGAIN )
						{
							continue;
						}
						else if( errno == EINTR )
						{
							continue;
						}
						tobe_myevent->fd = 0;
						close( sock_client );
						continue;
					}

					if( flag >0 )
					{
						tobe_myevent->sd_pos += flag;
						if( tobe_myevent->sd_pos >= sizeof( time_t ) )
						{
							tobe_myevent->fd = 0;
							close( sock_client );
							continue;
						}
					}
				}
				if( event_flag & EPOLLIN )
				{
					if( tobe_myevent->rc_pos < 64 )
					{
						flag = recv( sock_client, tobe_myevent->recv + tobe_myevent->rc_pos, 64 - tobe_myevent->rc_pos, 0 );
						if( flag <= 0 )
						{
							continue;
						}

						tobe_myevent->rc_pos += flag;

						if( tobe_myevent->rc_pos < 64 )
						{
							continue;
						}

						if( tobe_myevent->recv[31] || tobe_myevent->recv[63] )
						{
							printf( "your recv does follow the protocal\n");
							tobe_myevent->fd = 0;
							close( sock_client );
							continue;
						}

						flag = send( sock_client, tobe_myevent->send, sizeof( time_t ), 0 );
						if( flag < sizeof( time_t ) )
						{
							if( flag > 0 )
								tobe_myevent->sd_pos += flag;
							tobe_event.events = EPOLLET | EPOLLOUT;
							tobe_event.data.u32 = wait_events[i].data.u32;
							epoll_ctl( epfd, EPOLL_CTL_MOD, sock_client, &tobe_event );
							continue;
						}
						tobe_myevent->fd = 0;
						close( sock_client );
					}

				}
			}


		}
		
	}
	printf( "close server connection\n");
	close( sock_server );

	return 0;
	
}

你可能感兴趣的:(代码,开发,解析,服务器,大并发)