⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 usrsocklib.c

📁 基于Vxworks平台的几个代码(C)
💻 C
📖 第 1 页 / 共 2 页
字号:

#include "usrSockLib.h"
#include "usrTaskManager.h"
#include "core.h"


/************************************* 全局变量 *************************************/
static BOOL         G_STL_RUN        = FALSE;	/* STL运行标志 */
static MEMORIZER_ID G_STL_ServerList = NULL;	/* 服务器列表 */



/************************************* 内部函数 *************************************/

/* 服务器主任务入口函数 */
void STL_ServerTask( BOOL *Exit, HSoftDog hDog, int hServer )
{
	STL_Server      *pServer;	/* 服务器描述句柄 */
	fd_set			fd_rd;		/* 待读套接字组 */
#if 0
	char            in_buf[STL_MAX_INPUT_BUFFER];	/* 输入缓冲区 */
#endif
	char			in_buf[1];
	STL_Connection  *pConn, cn;	/* 客户连接项句柄 */
	int             i, sz;		/* 中间变量 */
	BOOL			bl;			/* 中间变量 */
	

	pServer = (STL_Server*)mem_mapaddr( G_STL_ServerList, (hServer - 1) );
	/**/
	pServer->tmo.tv_sec = pServer->tIdelMax / 1000000;
	pServer->tmo.tv_usec = pServer->tIdelMax % 1000000;
	
	while( !(*Exit) && pServer->state == STL_SERVER_STATE_NORMAL )
	{
		/* 喂狗 */
		SOFTDOG_SET( hDog, 100 );
		
		/* 设置套接字组 */
		FD_ZERO( &fd_rd );/* 清空 */
		FD_SET( pServer->sock, &fd_rd );/* 监听套接字 */
		if( pServer->bShareTask )
		{
			/* 添加该服务器上的所有连接的套接字 */
			for( i = 0; i < pServer->max_conn; i++ )
			{
				pConn = (STL_Connection*)mem_mapaddr( pServer->conn_list, i);
				if( pConn->state.flag == STL_CONN_STATE_NORMAL )
					FD_SET( pConn->sock, &fd_rd );
			}
		}

		switch( select(FD_SETSIZE, &fd_rd, NULL, NULL, &pServer->tmo) )
		{
		case 0:/* 超时(空闲) */
			/* 通知“空闲(可写)” */
			pServer->callback( hServer, STL_MSG_IDLE, 0, 0 );
			break;
		case SOCKET_ERROR:/* 出错 */
			/* 通知“服务器出错” */
			pServer->state = STL_SERVER_STATE_ERROR;
			pServer->callback( hServer, STL_MSG_ERROR, errnoGet(), 0 );
			break;
		default:
			/* 判断是否有新的连接请求 */
			if( FD_ISSET(pServer->sock, &fd_rd) )
			{
				/* 接受连接请求 */
				memset( &cn, 0, sizeof(cn) );
				sz = sizeof( cn.addr );
				cn.sock = accept( pServer->sock, (SOCKADDR*)&cn.addr, &sz );
				if( cn.sock != SOCKET_ERROR )
				{
					/* 设置socket属性 - KeepAlive */
					bl = TRUE;
					if( setsockopt(cn.sock, SOL_SOCKET, SO_KEEPALIVE, (char*)&bl, sizeof(BOOL)) == OK )
					{			
						/* 将连接添加至连接表 */
						cn.state.accepted = 0;
						cn.state.flag = STL_CONN_STATE_CONNECTED;
						i = mem_insert( pServer->conn_list, (BYTE*)&cn, sizeof(cn), NO_WAIT );
						if( i != -1 )
						{
							if( pServer->bAutoAccept )
							{
								if( STL_Accept(hServer) != -1 )
								{
									/* 通知"有新的连接" */
									bl = pServer->callback( hServer, STL_MSG_ACCEPT, STL_MAKE_CLIENT_HANDLE(hServer, i), 0 );
								}
								else
									bl = ERROR;
							}
							else
							{
								/* 通知"有新的连接" */
								bl = pServer->callback( hServer, STL_MSG_ACCEPT, STL_MAKE_CLIENT_HANDLE(hServer, i), 0 );
							}
							
							if( bl == ERROR )
							{
								/* 上层应用拒绝新连接 */
								shutdown( cn.sock, 2 );
								close( cn.sock );
								mem_delete( pServer->conn_list, i );
							}
						}
						else
						{
							/* 连接已满 */
							shutdown( cn.sock, 2 );
							close( cn.sock );
						}
					}
					else
					{
						/* 设置属性失败, 关闭之 */
						close( cn.sock );
					}
				}
			}
			
			if( pServer->bShareTask )
			{
				/* 遍历连接表同时检查某套接字是否为可读 */
				for( i = 0; i < pServer->max_conn; i++ )
				{
					pConn = (STL_Connection*)mem_mapaddr( pServer->conn_list, i);
					if( pConn->state.flag == STL_CONN_STATE_NORMAL )
					{
						/* 检查该套接字是否为可读 */
						if( FD_ISSET(pConn->sock, &fd_rd) )
						{
							/* 读数据 */
							/*sz = recv( pConn->sock, in_buf, STL_MAX_INPUT_BUFFER, 0 );*/
							sz = recv( pConn->sock, in_buf, 1, MSG_PEEK );
							if( sz > 0 )
							{
								/*pServer->callback( STL_MAKE_CLIENT_HANDLE(hServer, i), STL_MSG_DATA, sz, (int)in_buf );*/
								/* 通知“可读” */
								pServer->callback( STL_MAKE_CLIENT_HANDLE(hServer, i), STL_MSG_READ, 0, 0 );
							}
							else
							{
								/* 通知“连接中断” */
								pConn->state.flag = STL_CONN_STATE_ABORT;
								STL_Abort( STL_MAKE_CLIENT_HANDLE(hServer, i) );
								pServer->callback( STL_MAKE_CLIENT_HANDLE(hServer, i), STL_MSG_ABORT, 0, 0 );
							}
						}/* if( FD_ISSET(pConn->sock, &fd_rd) ) */
					}/* if( pConn->state.flag == STL_CONN_STATE_NORMAL ) */
				}/* for( ... ) */
			}/* if( pServer->bShareTask ) */
			
			/* 通知“空闲(可写)” */
			pServer->callback( hServer, STL_MSG_IDLE, 0, 0 );
		}/*switch*/
	}/* while( ... ) */
	
	STL_CloseServer( hServer );
}

/* 客户连接任务入口函数 */
void STL_ClientTask( BOOL *Exit, HSoftDog hDog, int hClient )
{
	STL_Server      *pServer;	/* 服务器描述句柄 */
	STL_Connection  *pConn;		/* 客户连接项句柄 */
	fd_set			fd_rd;		/* 待读套接字组 */
#if 0
	char            in_buf[STL_MAX_INPUT_BUFFER];	/* 输入缓冲区 */
#endif
	char			in_buf[1];
	int             sz;			/* 中间变量 */
	

	pServer = (STL_Server*)mem_mapaddr( G_STL_ServerList, (STL_GET_SERVER_HANDLE(hClient) - 1) );
	pConn = (STL_Connection*)mem_mapaddr( pServer->conn_list, STL_GET_CLIENT_HANDLE(hClient) );
	/**/
	pConn->tmo.tv_sec = pServer->tIdelMax / 1000000;
	pConn->tmo.tv_usec = pServer->tIdelMax % 1000000;
	
	while( !(*Exit) && 
			(pConn->state.flag == STL_CONN_STATE_CONNECTED ||
			 pConn->state.flag == STL_CONN_STATE_NORMAL) )
	{
		/* 喂狗 */
		SOFTDOG_SET( hDog, 40 );
		
		/* 设置待读套接字 */
		FD_ZERO( &fd_rd );/* 清空 */
		FD_SET( pConn->sock, &fd_rd );/* 监听套接字 */

		switch( select(pConn->sock + 1, &fd_rd, NULL, NULL, &pConn->tmo) )
		{
		case 0:/* 超时(空闲) */
			/* 通知“空闲(可写)” */
			pServer->callback( hClient, STL_MSG_IDLE, 0, 0 );
			break;
		case SOCKET_ERROR:/* 出错 */
			/* 通知“连接出错” */
			pConn->state.flag = STL_CONN_STATE_ERROR;
			pServer->callback( hClient, STL_MSG_ERROR, errnoGet(), 0 );
			break;
		default:
			/* 读取数据 */
			/*sz = recv( pConn->sock, in_buf, STL_MAX_INPUT_BUFFER, 0 );*/
			sz = recv( pConn->sock, in_buf, 1, MSG_PEEK );
			if( sz > 0 )
			{
				/*pServer->callback( hClient, STL_MSG_DATA, sz, (int)in_buf );*/
				/* 通知“可读” */
				pServer->callback( hClient, STL_MSG_READ, 0, 0 );
				
				/* 通知“空闲(可写)” */
				pServer->callback( hClient, STL_MSG_IDLE, 0, 0 );
			}
			else
			{
				/* 通知“连接中断” */
				pConn->state.flag = STL_CONN_STATE_ABORT;
				STL_Abort( hClient );
				pServer->callback( hClient, STL_MSG_ABORT, 0, 0 );
			}
			break;
		}/*switch*/
	}/* while( ... ) */
}



/************************************* 接口函数 *************************************/

/* 函数功能: 初始化传输层
*  参数说明:
*  max_servers[IN]: 最大支持服务端数
*  返回值:
*  成功则返回TRUE, 否则返回FALSE
*/
BOOL STL_Open( BYTE max_servers )
{
	if( !G_STL_RUN )
	{
		/* 创建服务器列表 */
		G_STL_ServerList = mem_build( MEMORIZER_TYPE_TABLE,
									  MEMORIZER_GROW_FIXED,
									  sizeof( STL_Server ),
									  max_servers == 0 ? STL_MAX_SERVER_NUMBER : max_servers );
									  
		G_STL_RUN = G_STL_ServerList != NULL;
	}
	
	return G_STL_RUN;
}

/* 函数功能: 关闭传输层 */
void STL_Close( void )
{
	UINT32 i, n;
	
	if( G_STL_RUN )
	{
		G_STL_RUN = FALSE;
		
		/* 停止所有服务器 */
		n = mem_get_number( G_STL_ServerList );
		for( i = 0; i < n; i++ )
		{
			STL_CloseServer( i + 1 );
		}
		
		/* 销毁服务器列表 */
		mem_release( G_STL_ServerList );
		G_STL_ServerList = NULL;
	}
}

/* 函数功能: 启动一个服务器
*  参数说明:
*  *server_name[IN]: 服务器名称(同时也是消息队列的名称)
*  *IP[IN]: 服务器监听地址
*  PORT[IN]: 服务器监听端口
*  max_conn[IN]: 最大连接数
*  bShareTask[IN]: 是否共享处理任务
*  bAutoAccept[IN]: 是否具有自行接受连接请求的权力
*  bKeepAlive[IN]: 是否需要keepalive维持
*  tIdelMax[IN]: 空闲单位时间(us)
*  taskPriority[IN]: 任务优先级
*  taskStack[IN]: 任务堆栈
*  callback[IN]: 回调函数
*  返回值:
*  启动成功则返回服务器句柄, 否则返回-1
*/
int STL_OpenServer( const char      *server_name,
					const char      *IP,
					USHORT          PORT,
				    USHORT          max_conn,
				    BOOL            bShareTask,
				    BOOL            bAutoAccept,
				    BOOL			bKeepAlive,
				    UINT32			tIdelMax,
				    UINT8			taskPriority,
				    int				taskStack,
				    STL_CallBack	callback )
				    
{
	STL_Server server;
	BOOL       addr_reuse;
	int        hServer = -1;
	BOOL       error   = TRUE;
	
	if( G_STL_RUN && server_name && IP && max_conn > 0 && callback )
	{
		if( strlen(server_name) >= sizeof(server.name) )
		{
			return -1;
		}
		
		/* 注册服务器 */
		hServer = mem_insert( G_STL_ServerList, (BYTE*)&server, sizeof(server), NO_WAIT );
		if( hServer >= 0 )
		{
			hServer += 1;
			
			/* 创建监听套接字 */
			server.sock = socket( AF_INET, SOCK_STREAM, 0 );
			if( server.sock != ERROR )
			{
				/* 将监听地址设为可重用 */
				addr_reuse = TRUE;
				if( setsockopt( server.sock,
								SOL_SOCKET,
								SO_REUSEADDR,
								(char*)&addr_reuse,
								sizeof(BOOL) ) == OK
								)
				{
					/* 邦定地址 */
					memset( &server.addr, 0, sizeof(server.addr) );
					server.addr.sin_len = sizeof( server.addr );
					server.addr.sin_family = AF_INET;
					server.addr.sin_port = htons( PORT );
					server.addr.sin_addr.s_addr = inet_addr( (char*)IP );
					if( bind(server.sock, (SOCKADDR*)&server.addr, sizeof(server.addr)) == OK )
					{
						/* 启动监听 */
						if( listen(server.sock, 0) == OK )
						{
							/* 创建连接表 */
							server.conn_list = mem_build( MEMORIZER_TYPE_TABLE,
														  MEMORIZER_GROW_FIXED,
														  sizeof( STL_Connection ),
														  max_conn );
							if( server.conn_list != NULL )
							{
								/* 设置服务器参数 */
								strcpy( server.name, server_name );
								server.state = STL_SERVER_STATE_NORMAL;
								server.bShareTask = bShareTask;
								server.bAutoAccept = bAutoAccept;
								server.bKeepAlive = bKeepAlive;
								server.max_conn = max_conn;
								server.tIdelMax = tIdelMax ? tIdelMax : 5000;
								server.taskPriority = taskPriority ? taskPriority : TASK_PRIORITY_STL_PROCESSOR;
								server.taskStack = taskStack > 1000 ? taskStack : TASK_STACKSIZE_STL_PROCESSOR;
								server.callback = callback;
								/* 更新服务器注册信息 */
								mem_update( G_STL_ServerList, (hServer - 1), (BYTE*)&server, sizeof(server), WAIT_FOREVER );
						
								/* 启动处理任务 */
								if( usrTaskCreate(TASK_TYPE_STL_PROCESSOR,
											      hServer,
											      0,
											      server.name,
											      server.taskPriority,
											      0,
											      server.taskStack,
											      (FUNCPTR)STL_ServerTask,
											      hServer,
											      0) )
								{	
									error = FALSE;
								}
								else
								{
									/* 删除连接表 */
									mem_release( server.conn_list );
								}
							}
						}/* listen */
					}/* bind */
				}/* setsockopt */
				
				if( error )
				{
					/* 关闭套接字 */
					shutdown( server.sock, 2 );
					close( server.sock );
				}
			}/* if( server.sock != ERROR ) */
			
			if( error )
			{
				/* 撤消服务器 */
				mem_delete( G_STL_ServerList, (hServer - 1) );
				hServer = -1;
			}
		}/* mem_insert */
	}
	
	return hServer;
}

/* 函数功能: 关闭一个服务器
*  参数说明:
*  hServer[IN]: 服务器句柄
*/
void STL_CloseServer( int hServer )
{
	STL_Server *pserver;
	STL_Connection *pconn;
	int        i;
	
	
	if( G_STL_RUN )
	{
		/* 获取服务器信息 */
		pserver = (STL_Server*)mem_mapaddr( G_STL_ServerList, (hServer - 1) );
		if( pserver )
		{
			if( pserver->state == STL_SERVER_STATE_NORMAL )
			{
				/* 删除处理任务 */
				pserver->state = STL_SERVER_STATE_CLOSE;
				usrTaskDelete( TASK_TYPE_STL_PROCESSOR,
							   hServer,
							   5000 );
				
				/* 关闭套接字 */
				shutdown( pserver->sock, 2 );
				close( pserver->sock );
				
				/* 删除所有客户的处理任务 */
				for( i = 0; i < pserver->max_conn; i++ )
				{
					/* 获取连接信息 */
					pconn = (STL_Connection*)mem_mapaddr( pserver->conn_list, i );
					if( pconn )
					{
						if( pconn->state.flag != STL_CONN_STATE_INVALID )
						{
							if( !pserver->bShareTask )
							{
								/* 结束客户连接处理任务 */
								pconn->state.flag = STL_CONN_STATE_ABORT;
								usrTaskDelete( TASK_TYPE_STL_CLIENT,
											   STL_MAKE_CLIENT_HANDLE(hServer, i),
											   NO_WAIT );
							}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -