📄 usrsocklib.c
字号:
#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 + -