|
|
/*****************************************************************************
|
|
|
* 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
|
|
|
|
|
|
int netWSAStartupErr = FALSE;
|
|
|
|
|
|
extern SIO_PARAM_DEF SioParam[];
|
|
|
|
|
|
extern u_short MaxSerialPortNum;
|
|
|
extern u_short MaxNetPortNum;
|
|
|
extern u_short MaxPortNum;
|
|
|
|
|
|
//创建 UDP 通讯 socket
|
|
|
BYTE CreateUdpSock(int *CommSock, DWORD NetPort, DWORD NetCommIpAddr)
|
|
|
{
|
|
|
int tmp, retval;
|
|
|
struct sockaddr_in addr;
|
|
|
u_long largp = 1L; //非阻塞模式
|
|
|
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
|
|
|
retval = ioctlsocket(*CommSock, FIONBIO, (u_long FAR *)&largp);
|
|
|
#endif
|
|
|
if (SOCKET_ERROR == retval)
|
|
|
{
|
|
|
|
|
|
// retval = WSAGetLastError();
|
|
|
// sprintf(tmp_buf, "ioctlsocket设置非阻塞模式错误, SocketError=%d, SocketId = %d", retval, *CommSock);
|
|
|
// DebugPrint(tmp_buf);
|
|
|
closesocket(*CommSock);
|
|
|
*CommSock = -1;
|
|
|
return FAIL_GREATE;
|
|
|
}
|
|
|
|
|
|
//设置socket输入输出缓冲
|
|
|
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广播通讯(广播地址)
|
|
|
if((NetCommIpAddr & 0x000000FF) == 0x000000FF)
|
|
|
{
|
|
|
setsockopt(*CommSock, SOL_SOCKET, SO_BROADCAST, (char*)&tmp, sizeof(tmp));
|
|
|
}
|
|
|
|
|
|
//让配置socket 能收不同网段的配置命令
|
|
|
//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
|
|
|
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探测次数
|
|
|
struct sockaddr_in addr;
|
|
|
u_long largp = 1L; //非阻塞模式
|
|
|
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);
|
|
|
*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
|
|
|
if (SOCKET_ERROR == retval)
|
|
|
{
|
|
|
// retval = WSAGetLastError();
|
|
|
// sprintf(tmp_buf, "ioctlsocket设置非阻塞模式错误, SocketError=%d, SocketId = %d", retval, *LiSock);
|
|
|
// DebugPrint(tmp_buf);
|
|
|
closesocket(*LiSock);
|
|
|
*LiSock = -1;
|
|
|
return FAIL_GREATE;
|
|
|
}
|
|
|
///设置socket的输入输出缓冲区大小
|
|
|
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接收所有连线
|
|
|
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
|
|
|
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探测次数
|
|
|
struct sockaddr_in addr;
|
|
|
u_long largp = 1L; //非阻塞模式
|
|
|
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
|
|
|
if (SOCKET_ERROR == tmp)
|
|
|
{
|
|
|
// tmp = WSAGetLastError();
|
|
|
// sprintf(tmp_buf, "ioctlsocket设置非阻塞模式错误, SocketError=%d, SocketId = %d", tmp, *CommSock);
|
|
|
// DebugPrint(tmp_buf);
|
|
|
closesocket(*CommSock);
|
|
|
*CommSock = -1;
|
|
|
return FAIL_GREATE;
|
|
|
}
|
|
|
|
|
|
///设置socket的输入输出缓冲区大小
|
|
|
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;
|
|
|
}
|
|
|
// 非阻塞的情况下不能这样使用
|
|
|
// 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探测次数
|
|
|
/*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 通讯
|
|
|
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 服务器通讯
|
|
|
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);
|
|
|
SioParam[i].LiSock = commsock;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
break;
|
|
|
|
|
|
case TCP_C_COMM: // TCP 客户通讯
|
|
|
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);
|
|
|
}
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
void CloseNetPort(int commid)
|
|
|
{
|
|
|
switch(SioParam[commid].NetType)
|
|
|
{
|
|
|
case UDP_COMM: // UDP 通讯
|
|
|
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 服务器通讯
|
|
|
if(SioParam[commid].CommSock > -1)
|
|
|
closesocket(SioParam[commid].CommSock);
|
|
|
//printf("关闭端口%d TCP客户端Socket=%d\n", commid+1, SioParam[commid].CommSock);
|
|
|
SioParam[commid].CommSock = -1;
|
|
|
if(CLOSE_PORT != SioParam[commid].OpenFlag)
|
|
|
{
|
|
|
SioParam[commid].OpenFlag = CLOSE_PORT;
|
|
|
}
|
|
|
break;
|
|
|
|
|
|
case TCP_C_COMM: // TCP 客户端通讯
|
|
|
if(SioParam[commid].CommSock > -1)
|
|
|
closesocket(SioParam[commid].CommSock);
|
|
|
|
|
|
SioParam[commid].CommSock = -1;
|
|
|
//printf("关闭端口%d TCP客户端Socket=%d\n", commid+1, SioParam[commid].CommSock);
|
|
|
if(CLOSE_PORT != SioParam[commid].OpenFlag)
|
|
|
{
|
|
|
SioParam[commid].OpenFlag = CLOSE_PORT;
|
|
|
}
|
|
|
break;
|
|
|
}
|
|
|
// 删除所有的发送缓冲区wen 2005.07.27
|
|
|
PortWriteDataFree(commid);
|
|
|
}
|
|
|
|
|
|
// TCP服务器端的侦听socket关闭与打开与端口是否打开的标识(SioParam[commid].OpenFlag)无关
|
|
|
void CloseNetListenPort(int commid)
|
|
|
{
|
|
|
int i;
|
|
|
|
|
|
switch(SioParam[commid].NetType)
|
|
|
{
|
|
|
case TCP_S_COMM: // TCP 服务器通讯
|
|
|
if(SioParam[commid].LiSock > -1)
|
|
|
//close(SioParam[commid].LiSock);
|
|
|
closesocket(SioParam[commid].LiSock);
|
|
|
SioParam[commid].LiSock = -1;
|
|
|
// 使用相同TCP服务端口的端口的listen套接字全部标识为-1(关闭)
|
|
|
for(i=MaxSerialPortNum; i<MaxPortNum; i++)
|
|
|
{
|
|
|
if(SioParam[i].LiSock == SioParam[commid].LiSock)
|
|
|
SioParam[i].LiSock = -1;
|
|
|
}
|
|
|
break;
|
|
|
case UDP_COMM: // UDP 通讯
|
|
|
break;
|
|
|
case TCP_C_COMM: // TCP 客户端通讯
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// UDP网络通讯接收数据
|
|
|
void UdpRecv(int commid, int fds, u_long ipaddr)
|
|
|
{
|
|
|
int len;
|
|
|
char revbuf[MAX_MSG_BUF_SIZE];
|
|
|
struct sockaddr_in addr;
|
|
|
#ifdef _WIN32
|
|
|
int addr_len = sizeof(struct sockaddr_in);
|
|
|
#else
|
|
|
socklen_t addr_len = sizeof(struct sockaddr_in);
|
|
|
#endif
|
|
|
|
|
|
// 将该socket中的数据读完
|
|
|
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);
|
|
|
}
|
|
|
|
|
|
//从头结点往后删
|
|
|
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;
|
|
|
|
|
|
// 错误判断和断点续传
|
|
|
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
|
|
|
//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
|
|
|
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);
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
if(!IsBaoHuPtr(commid))
|
|
|
{
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
if(NULL == SioParam[commid].WriteData)
|
|
|
{
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
// 增加错误判断和断点续传
|
|
|
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);
|
|
|
CloseNetPort(commid);
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
SioParam[commid].WriteData->PLen += len;
|
|
|
}
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
DelNode(commid);
|
|
|
}
|
|
|
|
|
|
//ShmAddSendCount(commid, len);
|
|
|
}
|
|
|
else if(EINPROGRESS != errno)
|
|
|
{
|
|
|
//printf("端口%d 不能发送数据,关闭Tcp通讯\n", commid+1);
|
|
|
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
|
|
|
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探测次数
|
|
|
fd_set set;
|
|
|
u_long largp = 1L; //非阻塞模式
|
|
|
char tmp_buf[256];
|
|
|
|
|
|
addr_len = sizeof(struct sockaddr_in);
|
|
|
//printf("端口%d 检查是否有客户端过来连接\n", commid+1);
|
|
|
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
|
|
|
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
|
|
|
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
|
|
|
if (SOCKET_ERROR == result)
|
|
|
{
|
|
|
// result = WSAGetLastError();
|
|
|
// sprintf(tmp_buf, "ioctlsocket设置非阻塞模式错误, SocketError=%d, SocketId = %d", result, sock);
|
|
|
// DebugPrint(tmp_buf);
|
|
|
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);
|
|
|
// 这里应该等到确定端口可以写再设置为完全打开状态
|
|
|
//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:有操作并有后续操作)
|
|
|
switch (SioParam[commid].NetType)
|
|
|
{
|
|
|
case NO_COMM:
|
|
|
break;
|
|
|
case UDP_COMM: // 检查UDP端口套接字是否建立
|
|
|
if (-1 < SioParam[commid].CommSock)
|
|
|
{
|
|
|
fds = SioParam[commid].CommSock;
|
|
|
setflag = 3;
|
|
|
break;
|
|
|
}
|
|
|
setflag = 2;
|
|
|
break;
|
|
|
case TCP_S_COMM: // 检查TCP服务器端口套接字是否建立(包括listen套接字)
|
|
|
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客户端套接字是否建立
|
|
|
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) 无需处理
|
|
|
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
|
|
|
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
|
|
|
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是否异常
|
|
|
if(FD_ISSET(fds, &fdset_ex))
|
|
|
{
|
|
|
CloseNetPort(commid);
|
|
|
break;
|
|
|
}
|
|
|
// socket可读
|
|
|
if(FD_ISSET(fds, &fdset_ro))
|
|
|
UdpRecv(commid, fds, ipaddr);// 将该socket中的数据读完
|
|
|
// socket可写
|
|
|
if(FD_ISSET(fds, &fdset_wr))
|
|
|
UdpSend(commid);
|
|
|
break;
|
|
|
case TCP_C_COMM:
|
|
|
if(SioParam[commid].CommSock < 0)
|
|
|
break;
|
|
|
// 判断socket是否异常
|
|
|
if(FD_ISSET(fds, &fdset_ex))
|
|
|
{
|
|
|
CloseNetPort(commid);
|
|
|
break;
|
|
|
}
|
|
|
// socket可读
|
|
|
if(FD_ISSET(fds, &fdset_ro))
|
|
|
{
|
|
|
if(TcpRecv(commid, fds, ipaddr) == FALSE) // 将该socket中的数据读完
|
|
|
break; // 端口可能已经关闭
|
|
|
}
|
|
|
// socket可写
|
|
|
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);
|
|
|
ok++;
|
|
|
}*/
|
|
|
if(fds < 0)
|
|
|
{
|
|
|
if(lisfds < 0)
|
|
|
break;
|
|
|
if(FD_ISSET(lisfds, &fdset_ex))
|
|
|
{
|
|
|
//printf("端口%d 关闭服务器端口\n", commid+1);
|
|
|
CloseNetListenPort(commid);
|
|
|
}
|
|
|
else if(FD_ISSET(lisfds, &fdset_ro))
|
|
|
{
|
|
|
TcpAccept(commid, lisfds);
|
|
|
}
|
|
|
break;
|
|
|
}
|
|
|
// 判断socket是否异常
|
|
|
if(FD_ISSET(fds, &fdset_ex))
|
|
|
{
|
|
|
//printf("端口%d socket异常,关闭Tcp通讯\n", commid+1);
|
|
|
CloseNetPort(commid);
|
|
|
break;
|
|
|
}
|
|
|
// socket可读
|
|
|
if(FD_ISSET(fds, &fdset_ro))
|
|
|
{
|
|
|
if(TcpRecv(commid, fds, ipaddr) == FALSE) // 将该socket中的数据读完
|
|
|
break; // 端口可能已经关闭
|
|
|
}
|
|
|
// socket可写
|
|
|
if(FD_ISSET(fds, &fdset_wr))
|
|
|
TcpSend(commid);
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
|
// 服务器端口读写数据
|
|
|
} |