You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

912 lines
23 KiB
C++

2 years ago
/*****************************************************************************
* FileName : netport.c *
* Programmer : Li Liangchu *
* Writen at : 2004.07.21 *
* Version : *
* Description: base on net comm sports driver *
* Last modify: 2004.07.21 *
*****************************************************************************/
//#include "serialport.h"
#include "netport.h"
#include "commport.h"
#include "common.h"
#ifndef _WIN32
#include <sys/ioctl.h>
#endif
2 years ago
int netWSAStartupErr = FALSE;
extern SIO_PARAM_DEF SioParam[];
extern u_short MaxSerialPortNum;
extern u_short MaxNetPortNum;
extern u_short MaxPortNum;
//创建 UDP 通讯 socket
2 years ago
BYTE CreateUdpSock(int *CommSock, DWORD NetPort, DWORD NetCommIpAddr)
{
int tmp, retval;
struct sockaddr_in addr;
u_long largp = 1L; //非阻塞模式
2 years ago
char tmp_buf[256];
if(*CommSock > -1)
return SOCKET_BEING;
if((NetPort == 0) && (NetCommIpAddr == 0))
return FAIL_GREATE;
*CommSock = socket(AF_INET, SOCK_DGRAM, 0);
if(*CommSock < 0)
{
*CommSock = -1;
return FAIL_GREATE;
}
// 将socket设置为非阻塞模式
#ifdef OS_UNIX
tmp = fcntl(*CommSock, F_GETFL, 0);
fcntl(*CommSock, F_SETFL, tmp|O_NONBLOCK);
#else
2 years ago
retval = ioctlsocket(*CommSock, FIONBIO, (u_long FAR *)&largp);
#endif
2 years ago
if (SOCKET_ERROR == retval)
{
// retval = WSAGetLastError();
// sprintf(tmp_buf, "ioctlsocket设置非阻塞模式错误, SocketError=%d, SocketId = %d", retval, *CommSock);
// DebugPrint(tmp_buf);
2 years ago
closesocket(*CommSock);
*CommSock = -1;
return FAIL_GREATE;
}
//设置socket输入输出缓冲
2 years ago
tmp = MAX_NET_BUF_SIZE;
setsockopt(*CommSock, SOL_SOCKET, SO_RCVBUF, (char*)&tmp, sizeof(tmp));
tmp = MAX_NET_BUF_SIZE;
setsockopt(*CommSock, SOL_SOCKET, SO_SNDBUF, (char*)&tmp, sizeof(tmp));
tmp = 1;
setsockopt(*CommSock, SOL_SOCKET, SO_KEEPALIVE, (char*)&tmp, sizeof(tmp));
setsockopt(*CommSock, SOL_SOCKET, SO_REUSEADDR, (char*)&tmp, sizeof(tmp));
// 增加udp广播通讯(广播地址)
2 years ago
if((NetCommIpAddr & 0x000000FF) == 0x000000FF)
{
setsockopt(*CommSock, SOL_SOCKET, SO_BROADCAST, (char*)&tmp, sizeof(tmp));
}
//让配置socket 能收不同网段的配置命令
2 years ago
//bzero(&addr, sizeof(addr));
memset((char*)&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_port = htons(NetPort);
addr.sin_addr.s_addr = htonl(INADDR_ANY);
if(bind(*CommSock, (struct sockaddr *)&addr, sizeof(addr)) < 0)
{
closesocket(*CommSock);
*CommSock = -1;
return FAIL_GREATE;
}
return SUCCEED_GREATE;
}
//创建 TCP Server socket
2 years ago
BYTE CreateTcpServerSock(int *LiSock, DWORD NetPort)
{
int i, tmp, ret, retval;
#ifdef _WIN32
int len;
#else
socklen_t len;
#endif
int keep_alive = 1; // 设定KeepAlive
int keep_idle = 5; // 开始首次KeepAlive探测前的TCP空闭时间(s)
int keep_interval = 3; // 两次KeepAlive探测间的时间间隔(s)
int keep_count = 3; // 判定断开前的KeepAlive探测次数
2 years ago
struct sockaddr_in addr;
u_long largp = 1L; //非阻塞模式
2 years ago
char tmp_buf[256];
if(-1 < *LiSock)
return SOCKET_BEING;
if(NetPort == 0)
return FAIL_GREATE;
*LiSock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
//len = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
//*LiSock = len;
if(*LiSock < 0)
{
// retval = WSAGetLastError();
// sprintf(tmp_buf, "ioctlsocket设置非阻塞模式错误, SocketError=%d, SocketId = %d", retval, *LiSock);
2 years ago
*LiSock = -1;
return FAIL_GREATE;
}
// 将socket设置为非阻塞模式
#ifdef OS_UNIX
tmp = fcntl(*LiSock, F_GETFL, 0);
fcntl(*LiSock, F_SETFL, tmp|O_NONBLOCK);
#else
retval = ioctlsocket(*LiSock, FIONBIO, (u_long FAR*)&largp);
#endif
2 years ago
if (SOCKET_ERROR == retval)
{
// retval = WSAGetLastError();
// sprintf(tmp_buf, "ioctlsocket设置非阻塞模式错误, SocketError=%d, SocketId = %d", retval, *LiSock);
// DebugPrint(tmp_buf);
2 years ago
closesocket(*LiSock);
*LiSock = -1;
return FAIL_GREATE;
}
///设置socket的输入输出缓冲区大小
2 years ago
tmp = MAX_NET_BUF_SIZE;
setsockopt(*LiSock, SOL_SOCKET, SO_RCVBUF, (char*)&tmp, sizeof(tmp));
tmp = MAX_NET_BUF_SIZE;
setsockopt(*LiSock, SOL_SOCKET, SO_SNDBUF, (char*)&tmp, sizeof(tmp));
len = 4;
tmp_buf[0] = 1;
tmp = setsockopt(*LiSock, SOL_SOCKET, SO_KEEPALIVE, tmp_buf, len);
tmp = getsockopt(*LiSock, SOL_SOCKET, SO_KEEPALIVE, tmp_buf, &len);
tmp = 1;
// setsockopt(*LiSock, SOL_SOCKET, SO_KEEPALIVE, (char*)&tmp, sizeof(tmp));
setsockopt(*LiSock, SOL_SOCKET, SO_REUSEADDR, (char*)&tmp, sizeof(tmp));
//set_keepalive(*LiSock, keep_alive, keep_idle, keep_interval, keep_count);
//让TCP接收所有连线
2 years ago
memset((char*)&addr,0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_port = htons(NetPort);
addr.sin_addr.s_addr = htonl(INADDR_ANY);
//printf("TIP_(%04d): Port = %d, NetCommIpAddr(%08x), addr.sin_addr.s_addr(%08x)\n", getpid(), commid+1, *NetCommIpAddr, addr.sin_addr.s_addr);
if(bind(*LiSock, (struct sockaddr *)&addr, sizeof(addr)) < 0)
{
//printf("errno = %d\n", errno);
//close(*LiSock);
closesocket(*LiSock);
*LiSock = -1;
return FAIL_GREATE;
}
//printf("succeed!\n");
ret = listen(*LiSock, 4);
if(ret < 0)
{
//close(*LiSock);
closesocket(*LiSock);
*LiSock = -1;
return FAIL_GREATE;
}
return SUCCEED_GREATE;
}
//创建 TCP Client socket
2 years ago
BYTE CreateTcpClientSock(int *CommSock, DWORD NetPort, DWORD NetCommIpAddr)
{
int tmp;
#ifdef _WIN32
int len;
#else
socklen_t len;
#endif
int keep_alive = 1; // 设定KeepAlive
int keep_idle = 5; // 开始首次KeepAlive探测前的TCP空闭时间
int keep_interval = 3; // 两次KeepAlive探测间的时间间隔
int keep_count = 3; // 判定断开前的KeepAlive探测次数
2 years ago
struct sockaddr_in addr;
u_long largp = 1L; //非阻塞模式
2 years ago
char tmp_buf[256];
if(-1 < *CommSock)
return SOCKET_BEING;
if((NetPort == 0) && (NetCommIpAddr == 0))
return FAIL_GREATE;
*CommSock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if(*CommSock < 0)
{
*CommSock = -1;
return FAIL_GREATE;
}
// 将socket设置为非阻塞模式
#ifdef OS_UNIX
tmp = fcntl(*CommSock, F_GETFL, 0);
fcntl(*CommSock, F_SETFL, tmp|O_NONBLOCK);
#else
tmp = ioctlsocket(*CommSock, FIONBIO, (u_long *)&largp);
#endif
2 years ago
if (SOCKET_ERROR == tmp)
{
// tmp = WSAGetLastError();
// sprintf(tmp_buf, "ioctlsocket设置非阻塞模式错误, SocketError=%d, SocketId = %d", tmp, *CommSock);
// DebugPrint(tmp_buf);
2 years ago
closesocket(*CommSock);
*CommSock = -1;
return FAIL_GREATE;
}
///设置socket的输入输出缓冲区大小
2 years ago
tmp = MAX_NET_BUF_SIZE;
setsockopt(*CommSock, SOL_SOCKET, SO_RCVBUF, (char*)&tmp, sizeof(tmp));
tmp = MAX_NET_BUF_SIZE;
setsockopt(*CommSock, SOL_SOCKET, SO_SNDBUF, (char*)&tmp, sizeof(tmp));
len = 4;
tmp_buf[0] = 1;
tmp = setsockopt(*CommSock, SOL_SOCKET, SO_KEEPALIVE, tmp_buf, len);
tmp = getsockopt(*CommSock, SOL_SOCKET, SO_KEEPALIVE, tmp_buf, &len);
tmp = 1;
// setsockopt(*CommSock, SOL_SOCKET, SO_KEEPALIVE, (char*)&tmp, sizeof(tmp));
setsockopt(*CommSock, SOL_SOCKET, SO_REUSEADDR, (char*)&tmp, sizeof(tmp));
// set_keepalive(*CommSock, keep_alive, keep_idle, keep_interval, keep_count);
//bzero(&addr, sizeof(addr));
memset((char*)&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_port = htons(NetPort);
addr.sin_addr.s_addr = htonl(NetCommIpAddr);
//printf("TIP_(%04d): Port = %d, connect(%08x)\n", getpid(), commid+1, *NetCommIpAddr);
if(connect(*CommSock, (struct sockaddr *)&addr, sizeof(addr)) != 0)
{
//printf(" connect error errno= %d, EINPROGRESS=%d\n", errno,EINPROGRESS);
if(EINPROGRESS != errno)
{
closesocket(*CommSock);
//printf(" connect error errno= %d, EINPROGRESS=%d\n", errno,EINPROGRESS);
*CommSock = -1;
return FAIL_GREATE;
}
// 非阻塞的情况下不能这样使用
2 years ago
// else
// {
// if(connect(*CommSock, (struct sockaddr *)&addr, sizeof(addr)) < 0)
// {
// //printf(" connect error errno= %d, EISCONN=%d\n", errno,EISCONN);
// if(EISCONN != errno)
// {
// printf(" connect error errno= %d, EISCONN=%d\n", errno,EISCONN);
// close(*CommSock);
// *CommSock = -1;
// return FAIL_GREATE;
// }
// }
// //printf(" connect succeed errno= %d EISCONN=%d\n", errno, EISCONN);
// }
}
return SUCCEED_GREATE;
}
//int keep_alive = 1;//设定KeepAlive
//int keep_idle = 1;//开始首次KeepAlive探测前的TCP空闭时间
//int keep_interval = 1;//两次KeepAlive探测间的时间间隔
//int keep_count = 3;//判定断开前的KeepAlive探测次数
2 years ago
/*void set_keepalive(int fd, int keep_alive, int keep_idle, int keep_interval, int keep_count)
{
if(keep_alive)
{
if(setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, (void*)&keep_alive, sizeof(keep_alive)) == -1)
{
fprintf(stderr, "setsockopt SOL_SOCKET::SO_KEEPALIVE failed, %s\n",strerror(errno));
}
if(setsockopt(fd, SOL_TCP, TCP_KEEPIDLE, (void *)&keep_idle,sizeof(keep_idle)) == -1)
{
fprintf(stderr, "setsockopt SOL_TCP::TCP_KEEPIDLE failed, %s\n", strerror(errno));
}
if(setsockopt(fd,SOL_TCP,TCP_KEEPINTVL, (void *)&keep_interval, sizeof(keep_interval)) == -1)
{
fprintf(stderr, "setsockopt SOL_tcp::TCP_KEEPINTVL failed, %s\n", strerror(errno));
}
if(setsockopt(fd,SOL_TCP,TCP_KEEPCNT, (void *)&keep_count,sizeof(keep_count)) == -1)
{
fprintf(stderr, "setsockopt SOL_TCP::TCP_KEEPCNT failed, %s\n", strerror(errno));
}
}
}*/
void OpenNetPort(int commid)
{
BYTE succeedflag;
int i, commsock;
DWORD netport, netcommipaddr;
commsock = SioParam[commid].CommSock;
netport = SioParam[commid].NetPort;
netcommipaddr = SioParam[commid].NetCommIpAddr;
switch(SioParam[commid].NetType)
{
case UDP_COMM: // UDP 通讯
2 years ago
if(OPEN_PORT == SioParam[commid].OpenFlag)
return;
succeedflag = CreateUdpSock(&commsock, netport, netcommipaddr);
if(SUCCEED_GREATE == succeedflag)
{
SioParam[commid].OpenFlag = OPEN_PORT;
SioParam[commid].CommSock = commsock;
}
break;
case TCP_S_COMM: // TCP 服务器通讯
2 years ago
commsock = SioParam[commid].LiSock;
succeedflag = CreateTcpServerSock(&commsock, netport);
if(SUCCEED_GREATE == succeedflag)
{
for(i=MaxSerialPortNum; i<MaxPortNum; i++)
{
if(TCP_S_COMM == SioParam[i].NetType)
{
if(SioParam[i].NetPort == netport)
{
printf("端口%d netport=%d lisock=%d\n", i+1, netport, commsock);
2 years ago
SioParam[i].LiSock = commsock;
}
}
}
}
break;
case TCP_C_COMM: // TCP 客户通讯
2 years ago
if(OPEN_PORT == SioParam[commid].OpenFlag)
return;
succeedflag = CreateTcpClientSock(&commsock, netport, netcommipaddr);
if(SUCCEED_GREATE == succeedflag)
{
SioParam[commid].CommSock = commsock;
//if(commid == 8)
//printf("端口%d 创建TCP 客户端成功socket=%d\n", commid+1, SioParam[commid].CommSock);
2 years ago
}
break;
}
}
void CloseNetPort(int commid)
{
switch(SioParam[commid].NetType)
{
case UDP_COMM: // UDP 通讯
2 years ago
if(SioParam[commid].CommSock > -1)
closesocket(SioParam[commid].CommSock);
SioParam[commid].CommSock = -1;
if(CLOSE_PORT != SioParam[commid].OpenFlag)
{
SioParam[commid].OpenFlag = CLOSE_PORT;
}
break;
case TCP_S_COMM: // TCP 服务器通讯
2 years ago
if(SioParam[commid].CommSock > -1)
closesocket(SioParam[commid].CommSock);
//printf("关闭端口%d TCP客户端Socket=%d\n", commid+1, SioParam[commid].CommSock);
2 years ago
SioParam[commid].CommSock = -1;
if(CLOSE_PORT != SioParam[commid].OpenFlag)
{
SioParam[commid].OpenFlag = CLOSE_PORT;
}
break;
case TCP_C_COMM: // TCP 客户端通讯
2 years ago
if(SioParam[commid].CommSock > -1)
closesocket(SioParam[commid].CommSock);
SioParam[commid].CommSock = -1;
//printf("关闭端口%d TCP客户端Socket=%d\n", commid+1, SioParam[commid].CommSock);
2 years ago
if(CLOSE_PORT != SioParam[commid].OpenFlag)
{
SioParam[commid].OpenFlag = CLOSE_PORT;
}
break;
}
// 删除所有的发送缓冲区wen 2005.07.27
2 years ago
PortWriteDataFree(commid);
}
// TCP服务器端的侦听socket关闭与打开与端口是否打开的标识(SioParam[commid].OpenFlag)无关
2 years ago
void CloseNetListenPort(int commid)
{
int i;
switch(SioParam[commid].NetType)
{
case TCP_S_COMM: // TCP 服务器通讯
2 years ago
if(SioParam[commid].LiSock > -1)
//close(SioParam[commid].LiSock);
closesocket(SioParam[commid].LiSock);
SioParam[commid].LiSock = -1;
// 使用相同TCP服务端口的端口的listen套接字全部标识为1(关闭)
2 years ago
for(i=MaxSerialPortNum; i<MaxPortNum; i++)
{
if(SioParam[i].LiSock == SioParam[commid].LiSock)
SioParam[i].LiSock = -1;
}
break;
case UDP_COMM: // UDP 通讯
2 years ago
break;
case TCP_C_COMM: // TCP 客户端通讯
2 years ago
break;
}
}
// UDP网络通讯接收数据
2 years ago
void UdpRecv(int commid, int fds, u_long ipaddr)
{
int len;
char revbuf[MAX_MSG_BUF_SIZE];
struct sockaddr_in addr;
#ifdef _WIN32
2 years ago
int addr_len = sizeof(struct sockaddr_in);
#else
socklen_t addr_len = sizeof(struct sockaddr_in);
#endif
2 years ago
// 将该socket中的数据读完
2 years ago
do
{
len = recvfrom(fds, revbuf, MAX_MSG_BUF_SIZE, 0, (struct sockaddr *)&addr, &addr_len);
if(addr.sin_addr.s_addr == ipaddr)
{
if(IsBaoHuPtr(commid))
{
PutDataToBuf(&SioParam[commid].RecvBuf, (u_char*)revbuf, len);
}
}
}while(len >= MAX_MSG_BUF_SIZE);
}
//从头结点往后删
2 years ago
void DelNode(int commid)
{
struct WR_DATA *next;
if (!SioParam[commid].WriteData)
{
return;
}
//SioParam[commid].iWriteDataNo--;
next = SioParam[commid].WriteData->Next;
HEAP_FREE(SioParam[commid].WriteData);
SioParam[commid].WriteData = next;
}
void UdpSend(int commid)
{
int len, plen, slen;
struct sockaddr_in addr;
if(!IsBaoHuPtr(commid))
return;
if(NULL == SioParam[commid].WriteData)
return;
//bzero(&addr, sizeof(addr));
memset((char*)&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_port = htons(SioParam[commid].NetPort);
addr.sin_addr.s_addr = SioParam[commid].NetCommIpAddr;
// 错误判断和断点续传
2 years ago
plen = SioParam[commid].WriteData->PLen;
slen = SioParam[commid].WriteData->MsgLen - plen;
if(slen <= 0)
{
DelNode(commid);
return;
}
len = sendto(SioParam[commid].CommSock,(const char*)&SioParam[commid].WriteData->MsgData[plen], slen,
0, (struct sockaddr *)&addr, sizeof(struct sockaddr_in));
if(len > 0)
{
if(len < slen)
{
if(EINPROGRESS != errno)
{
CloseNetPort(commid);
}
else
{
SioParam[commid].WriteData->PLen += len;
}
}
else
{
DelNode(commid);
}
//ShmAddSendCount(commid, len);
}
else if(EINPROGRESS != errno)
{
CloseNetPort(commid);
}
}
BOOL TcpRecv(int commid, int fds, u_long ipaddr)
{
BOOL bRetVal;
int len, nread;
char revbuf[MAX_MSG_BUF_SIZE];
// if(OPEN_PORT != SioParam[commid].OpenFlag)
// return FALSE;
bRetVal = TRUE;
//删除已断开的子socket
2 years ago
//ioctl(fds, FIONREAD, &nread);
/*if(nread == 0)
{
//if(commid == 8)
// printf("TIP_(%04d): Port=%d Peer Socket is closed already.\n", getpid(), commid+1);
CloseNetPort(commid);
bRetVal = FALSE;
}
else*/
{
do
{
len = recv(fds, revbuf, MAX_MSG_BUF_SIZE, 0);
// 错误判断 len = 0 有可能是对方已经关闭socket
2 years ago
if(len <= 0)
{
printf("port%d read error len=%d\n", commid+1, len);
if(EINPROGRESS != errno)
{
//printf("port%d read error\n", commid+1);
CloseNetPort(commid);
bRetVal = FALSE;
break;
}
}
if(IsBaoHuPtr(commid))
{
PutDataToBuf(&SioParam[commid].RecvBuf, (u_char*)revbuf, len);
}
}while(len >= MAX_MSG_BUF_SIZE);
}
return bRetVal;
}
void TcpSend(int commid)
{
int len, plen, slen;
if(OPEN_PORT != SioParam[commid].OpenFlag)
{
SioParam[commid].OpenFlag = OPEN_PORT;
//printf("设置Tcp端口%d 端口状态为OPEN_PORT\n", commid+1);
2 years ago
}
else
{
if(!IsBaoHuPtr(commid))
{
return;
}
if(NULL == SioParam[commid].WriteData)
{
return;
}
// 增加错误判断和断点续传
2 years ago
plen = SioParam[commid].WriteData->PLen;
slen = SioParam[commid].WriteData->MsgLen - plen;
if(slen <= 0)
{
DelNode(commid);
return;
}
len = send(SioParam[commid].CommSock,(const char*)&SioParam[commid].WriteData->MsgData[plen], slen, 0);
if(len > 0)
{
if(len < slen)
{
if(EINPROGRESS != errno)
{
//printf("端口%d 发送错误关闭Tcp通讯\n", commid+1);
2 years ago
CloseNetPort(commid);
}
else
{
SioParam[commid].WriteData->PLen += len;
}
}
else
{
DelNode(commid);
}
//ShmAddSendCount(commid, len);
}
else if(EINPROGRESS != errno)
{
//printf("端口%d 不能发送数据关闭Tcp通讯\n", commid+1);
2 years ago
CloseNetPort(commid);
}
}
}
void TcpAccept(int commid, int lisfds)
{
int sock, i, tmp;
#ifdef _WIN32
int result, addr_len;
#else
socklen_t result, addr_len;
#endif
2 years ago
struct sockaddr_in addr;
int keep_alive = 1; // 设定KeepAlive
int keep_idle = 5; // 开始首次KeepAlive探测前的TCP空闭时间
int keep_interval = 3; // 两次KeepAlive探测间的时间间隔
int keep_count = 3; // 判定断开前的KeepAlive探测次数
2 years ago
fd_set set;
u_long largp = 1L; //非阻塞模式
2 years ago
char tmp_buf[256];
addr_len = sizeof(struct sockaddr_in);
//printf("端口%d 检查是否有客户端过来连接\n", commid+1);
2 years ago
sock = accept(lisfds, (struct sockaddr *)&addr, &addr_len);
if(sock < 0)
{
return;
}
printf("TIP_(%04d): Port = %d, addr.sin_addr.s_addr(%08x), sock = %d\n", _getpid(), commid+1, addr.sin_addr.s_addr, sock);
// 多客户端向服务端连接时判断客户端来自的端口号 yizhonghu 20070704
2 years ago
for(i=MaxSerialPortNum; i<MaxPortNum; i++)
{
if((SioParam[i].NetCommIpAddr == addr.sin_addr.s_addr)
&& (SioParam[i].LiSock == lisfds))
{
printf("sockport = %d\n", i+1);
commid = i;
break;
}
}
if(i == MaxPortNum)
{
closesocket(sock);
return;
}
// 如果socket已经存在则关掉原来的连接建立新的连接 yizhonghu 20070705
2 years ago
if(SioParam[commid].CommSock < 0)
{
closesocket(SioParam[commid].CommSock);
}
SioParam[commid].CommSock = sock;
#ifdef OS_UNIX
result = fcntl(sock, F_GETFL, 0);
fcntl(sock, F_SETFL, result|O_NONBLOCK);
#else
result = ioctlsocket(sock, FIONBIO, (u_long *)&largp);
#endif
2 years ago
if (SOCKET_ERROR == result)
{
// result = WSAGetLastError();
// sprintf(tmp_buf, "ioctlsocket设置非阻塞模式错误, SocketError=%d, SocketId = %d", result, sock);
// DebugPrint(tmp_buf);
2 years ago
return;
}
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
result = MAX_NET_BUF_SIZE;
setsockopt(sock, SOL_SOCKET, SO_RCVBUF, (char*)&result, sizeof(result));
result = MAX_NET_BUF_SIZE;
setsockopt(sock, SOL_SOCKET, SO_SNDBUF, (char*)&result, sizeof(result));
result = 4;
tmp_buf[0] = 1;
tmp = setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, tmp_buf, result);
tmp = getsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, tmp_buf, &result);
result = 1;
setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char*)&result, sizeof(result));
//set_keepalive(sock, keep_alive, keep_idle, keep_interval, keep_count);
// 这里应该等到确定端口可以写再设置为完全打开状态
2 years ago
//SioParam[commid].OpenFlag = OPEN_PORT;
}
int AddFdToSet(int commid, int *fd_max, fd_set *fdset_ro, fd_set *fdset_wr, fd_set *fdset_ex)
{
int setflag, fds, inum;
inum = 0;
setflag = 0;// (=0: 无操作; =1:没有后续操作; =2:当前无操作,但有后续操作;=3:有操作并有后续操作)
2 years ago
switch (SioParam[commid].NetType)
{
case NO_COMM:
break;
case UDP_COMM: // 检查UDP端口套接字是否建立
2 years ago
if (-1 < SioParam[commid].CommSock)
{
fds = SioParam[commid].CommSock;
setflag = 3;
break;
}
setflag = 2;
break;
case TCP_S_COMM: // 检查TCP服务器端口套接字是否建立(包括listen套接字)
2 years ago
if ((0 > SioParam[commid].CommSock) && (-1 < SioParam[commid].LiSock))
{
fds = SioParam[commid].LiSock;
setflag = 3;
break;
}
if (-1 < SioParam[commid].CommSock)
{
fds = SioParam[commid].CommSock;
setflag = 3;
break;
}
setflag = 2;
break;
case TCP_C_COMM: // 检查TCP客户端套接字是否建立
2 years ago
if (-1 < SioParam[commid].CommSock)
{
fds = SioParam[commid].CommSock;
setflag = 3;
break;
}
setflag = 2;
break;
}
if (0 == setflag)
return inum;
if ((1 == setflag) || (3 == setflag))
{
inum++;
FD_SET(fds, fdset_ro);
FD_SET(fds, fdset_wr);
FD_SET(fds, fdset_ex);
*fd_max = max(*fd_max, fds);
}
if (1 == setflag)
return inum;
// if(2 == setflag) 无需处理
2 years ago
return inum;
}
void PollAllPort(void)
{
struct timeval timeout;
int i, inum, nfds, commid, fds, lisfds, ret, ierr;
#ifdef _WIN32
int ierrlen;
#else
socklen_t ierrlen;
#endif
2 years ago
u_long ipaddr;
fd_set fdset_ro, fdset_wr, fdset_ex;
/*static int ok=0;*/
inum = 0;
nfds = 0;
FD_ZERO(&fdset_ro);
FD_ZERO(&fdset_wr);
FD_ZERO(&fdset_ex);
for(i=0; i<MaxPortNum; i++)
{
commid = i;
inum += AddFdToSet(commid, &nfds, &fdset_ro, &fdset_wr, &fdset_ex);
}
if(inum < 1)
return;
// 设置超时等待时间为0
2 years ago
memset((char*)&timeout, 0, sizeof(struct timeval));
if(select(nfds+1, &fdset_ro, &fdset_wr, &fdset_ex, &timeout) < 1)
{
return;
}
for(i=0; i< MaxPortNum; i++)
{
commid = i;
fds = SioParam[commid].CommSock;
ipaddr = SioParam[commid].NetCommIpAddr;
switch(SioParam[commid].NetType)
{
case NO_COMM:
break;
case UDP_COMM:
if(SioParam[commid].CommSock < 0)
break;
// 判断socket是否异常
2 years ago
if(FD_ISSET(fds, &fdset_ex))
{
CloseNetPort(commid);
break;
}
// socket可读
2 years ago
if(FD_ISSET(fds, &fdset_ro))
UdpRecv(commid, fds, ipaddr);// 将该socket中的数据读完
// socket可写
2 years ago
if(FD_ISSET(fds, &fdset_wr))
UdpSend(commid);
break;
case TCP_C_COMM:
if(SioParam[commid].CommSock < 0)
break;
// 判断socket是否异常
2 years ago
if(FD_ISSET(fds, &fdset_ex))
{
CloseNetPort(commid);
break;
}
// socket可读
2 years ago
if(FD_ISSET(fds, &fdset_ro))
{
if(TcpRecv(commid, fds, ipaddr) == FALSE) // 将该socket中的数据读完
break; // 端口可能已经关闭
2 years ago
}
// socket可写
2 years ago
if(FD_ISSET(fds, &fdset_wr))
{
ierrlen = sizeof(ierr);
ret = getsockopt (fds, SOL_SOCKET, SO_ERROR, (char *)&ierr, &ierrlen);
if (SOCKET_ERROR == ret)
{
CloseNetPort(commid);
break;
}
TcpSend(commid);
}
break;
case TCP_S_COMM:
lisfds = SioParam[commid].LiSock;
/*if(ok < 1000)
{
printf("端口%d lisock=%d fds = %d\n", commid+1, lisfds, fds);
2 years ago
ok++;
}*/
if(fds < 0)
{
if(lisfds < 0)
break;
if(FD_ISSET(lisfds, &fdset_ex))
{
//printf("端口%d 关闭服务器端口\n", commid+1);
2 years ago
CloseNetListenPort(commid);
}
else if(FD_ISSET(lisfds, &fdset_ro))
{
TcpAccept(commid, lisfds);
}
break;
}
// 判断socket是否异常
2 years ago
if(FD_ISSET(fds, &fdset_ex))
{
//printf("端口%d socket异常关闭Tcp通讯\n", commid+1);
2 years ago
CloseNetPort(commid);
break;
}
// socket可读
2 years ago
if(FD_ISSET(fds, &fdset_ro))
{
if(TcpRecv(commid, fds, ipaddr) == FALSE) // 将该socket中的数据读完
break; // 端口可能已经关闭
2 years ago
}
// socket可写
2 years ago
if(FD_ISSET(fds, &fdset_wr))
TcpSend(commid);
break;
}
}
// 服务器端口读写数据
2 years ago
}