Linux select的问题

scorpio_tiger 2009-10-26 10:10:34
问题描述如下:
客户端在有数据发送时,调用connect(...)连接客户端,然后发送数据,发送完成后。马上断开。为此服务器(为Linux RH9)端采用select模型。但程序测试的时候发现只在客户端第一次连接的时候能否接受到数据(select函数有返回)。第二次连接及以后的连接服务器(select函数无返回)。代码如下,大家帮我看下..
【Server端】
void mod_sec_log_thread(void)
{
trace_log("enter mod_sec_log htread....", 9);

struct sockaddr_in address;
int sockListen = socket(AF_INET, SOCK_STREAM, 0);
int tmpSocket;

int cirSocket;
int nSelectRet = 0;
int nCircle = 0;
int nRecv = 0;

int comSockArray[MAX_SOCKET_ARRAY];
int nCurrentConnection = 0;

char szSockRecvBuf[MAX_int_BUF];

struct sockaddr_in tmpAddr;
int nAddressLen = sizeof(struct sockaddr_in);

int address_len = 0;


if ( -1 == sockListen )
{
trace_log("Create ModSecurity List Socket Error", 9);
return;
}

address.sin_family = AF_INET;
address.sin_addr.s_addr = htonl(INADDR_ANY);
address.sin_port = htons(LOCAL_LISTEN_PORT);
address_len = sizeof(address);



if ( -1 == bind(sockListen, &address, address_len))
{
trace_log("error bind...", 9);
return;
}

if (listen(sockListen, 5) == -1)
{
trace_log("error Listen...", 9);
return;
}


fd_set fdread;
FD_ZERO(&fdread);
FD_SET(sockListen,&fdread);

reset_socket_array(comSockArray, MAX_SOCKET_ARRAY);

// just MAX_SOCKET_ARRAY - 1 can comunicate
add_socket_array(sockListen, comSockArray, MAX_SOCKET_ARRAY);
nCurrentConnection++;



while ( 1 )
{
trace_log("enter mod_log...", 9);

int maxSock = get_max_socket_array(comSockArray, MAX_SOCKET_ARRAY);

printf("maxSock: %d\n CurrentConnection: %d\n", maxSock, nCurrentConnection);


nSelectRet = select(maxSock + 1,
&fdread,
NULL,
NULL,
NULL);

trace_log("after select.......................", 9);

if ( nSelectRet <= 0 )
{
continue;
}


// new connection
if ( FD_ISSET(sockListen, &fdread) )
{
trace_log("a connection is comming....", 9);

if ( nCurrentConnection > MAX_SOCKET_ARRAY )
{
trace_log("too much connections...", 9);
}
else
{
trace_log("add to socket array....", 9);
printf("current connection:%d\n", nCurrentConnection);

tmpSocket = accept(sockListen, &tmpAddr, &nAddressLen);

printf("new socket: %d\n", tmpSocket);

FD_SET(tmpSocket, &fdread);

add_socket_array(tmpSocket, comSockArray, MAX_SOCKET_ARRAY);

// add connection count
nCurrentConnection++;
}
}


// communicate event


for ( nCircle = 0; nCircle < MAX_SOCKET_ARRAY; nCircle++ )
{
cirSocket = comSockArray[nCircle];
if ( FD_ISSET(cirSocket, &fdread) && cirSocket != sockListen)
{

nRecv = recv(cirSocket, szSockRecvBuf, MAX_int_BUF, 0);
if ( nRecv < 0 )
{
trace_log("recv Error...", 9);
continue;
}

// client closeSocket
if ( 0 == nRecv )
{
trace_log("Client closeSocket....", 9);


FD_CLR(cirSocket, &fdread);
clr_socket_array(cirSocket, comSockArray, MAX_SOCKET_ARRAY);

nCurrentConnection--;
continue;
}

else
{
szSockRecvBuf[nRecv] = '\0';
trace_log("recved somthing...", 9);
trace_log(szSockRecvBuf, 9);
}
}
}
}

}


【Client端】 客户端分别写了3个函数(连接、发送、关闭)。 单线程调用这三方函数

static int sock;

int ConnectToNPServer(const char * szIP,int nPort)
{
struct sockaddr_in server_addr;
sock = socket(AF_INET, SOCK_STREAM, 0);
if( sock < 0 )
{
return 1;
}
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(nPort);
server_addr.sin_addr.s_addr = inet_addr(szIP);
memset(server_addr.sin_zero,0,8);

if (connect(sock, (struct sockaddr *) & server_addr,sizeof (struct sockaddr)) == -1)
{
sock = -1;
return 1;
}
return 0;
}

int SendBuf(const char* buf, int size)
{
if( sock < 0)
{
return 1;
}
else
{
if(send(sock,buf,strlen(buf),0) == -1)
{
cout << "Error Send" << WSAGetLastError() << endl;
return 1;
}
return 0;
}
}

void DisConnect()
{
if( sock < 0)
{
return;
}
closesocket(sock);
}


////////发送部分:
DWORD MyThreadFunction1( LPVOID lpParam )
{


for(int i = 0; i < 10;i++)
{
ConnectToNPServer(DES_IP_ADDRESS, DES_PORT);

SendBuf("0123456789--------------------------------------------", 30);

DisConnect();
Sleep(5000);
}


return 0;
}
...全文
103 3 打赏 收藏 转发到动态 举报
写回复
用AI写文章
3 条回复
切换为时间正序
请发表友善的回复…
发表回复
scorpio_tiger 2009-10-27
  • 打赏
  • 举报
回复
感谢sun007700,问题已经解决。但能否解释下原因?
sun007700 2009-10-27
  • 打赏
  • 举报
回复
“ nSelectRet = select(maxSock + 1,
&fdread,
NULL,
NULL,
NULL);

写成

nSelectRet = select(maxSock + 1,
&fdread,
NULL,
NULL,
&val);

sun007700 2009-10-27
  • 打赏
  • 举报
回复
"fd_set fdread;
FD_ZERO(&fdread);
FD_SET(sockListen,&fdread);
"
放在 while循环里select函数前
另外,select最后一个参数是timeout,设置它的属性
timeval val;
val.tv_sec = 10; //秒
val.tv_usec = 0;
也放在while函数里select函数前。

23,125

社区成员

发帖
与我相关
我的任务
社区描述
Linux/Unix社区 应用程序开发区
社区管理员
  • 应用程序开发区社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧