请问,为什么一加上超时控制,就没有数据传输了呢?

swxlion 2004-09-01 04:12:53
RT。

三个问题,希望能一一解答。谢谢!

1.为什么不打开超时控制的代码(注释),我的程序就很正常,而一打开就没有数据传输了呢?

2.单开Client(不开服务器)的时候,为什么程序马上就打飞(自动退出)呢?

3.为什么在Client.cpp中,打开bind相关代码,且关闭超时控制相关代码时,没有数据传输呢?

源代码附后。

(注1:服务器端:CS.cpp;客户端:Client.cpp。)
(注2:使用ws2_32.lib。)
(注3:bind和超时控制相关代码已被注释掉,要打开只需取消相关代码的注释即可。)
...全文
195 13 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
13 条回复
切换为时间正序
请发表友善的回复…
发表回复
swxlion 2004-09-02
  • 打赏
  • 举报
回复
好了,现在解决了.
的确如msdn_user(蓝天) 和skyupsky(北方舞者) 所说,
是由于connect失败;
或者在连接时中断时,在while循环后select返回SOCKET_ERROR,然后break退出.
是我当时太心急,又太粗心了。

谢谢大家!^_^
skyupsky 2004-09-01
  • 打赏
  • 举报
回复
应该不断的connect,直到连接上或者程序退出才跳出!
msdn_user 2004-09-01
  • 打赏
  • 举报
回复
connect失败导致进入下面的while循环后
select返回SOCKET_ERROR
然后break以后退出了
我想应该是这样的吧
PiggyXP 2004-09-01
  • 打赏
  • 举报
回复
乖乖,这么多

不过哪里有超时控制的代码呢?你是说select的那几行吗?那不是超时控制的,在你的代码里面,那几行也是没有必要加的
PiggyXP 2004-09-01
  • 打赏
  • 举报
回复
1.用select设置超时是这样的

//select 模型,即设置超时
struct timeval timeout ;
fd_set r;

FD_ZERO(&r);
FD_SET(cClient, &r);
timeout.tv_sec = 15; //连接超时15秒
timeout.tv_usec =0;
ret = select(0, 0, &r, 0, &timeout);

2.这样是把socket设置为非阻塞模式
unsigned long ul = 1;
ret = ioctlsocket(cClient, FIONBIO, (unsigned long*)&ul);

3.如果connect是立即返回,请检查一下你是不是你把socket设置为非阻塞了?
如果connect过段时间才返回是正常情况,阻塞socket是有一个默认的超时时间的
swxlion 2004-09-01
  • 打赏
  • 举报
回复
谢谢msdn_user(蓝天),client的代码是有问题,我在改写的时候给漏了。
现在一切度正常了,数据收发也没问题了,只剩下最后一个问题:
就只是不知为什么,客户端在服务器没开的情况下会自动退出,而不是等待?

Client.cpp

... ...
int WSMainConnect( )
{
WSAStartup( wVersionRequested, &wsaData );
... ...
WSWorkSocket = socket( AF_INET, SOCK_STREAM, WSCProto->p_proto );
... ...
connect( WSWorkSocket, ( struct sockaddr * )&servAddr, sizeof( servAddr ) );
... ...
while( true )
{
strcpy(dd,"asdghfghgf");
ret = send( WSWorkSocket, dd, strlen(dd), 0 );
... ...
ret = recv( WSWorkSocket, dd, strlen(dd), 0 );
.. ..
}
}
... ...
}

int main()
{
... ...
WSMainConnect( );
return 1;
}
//(以上为精简代码,完整代码在第二个回复中。)

msdn_user 2004-09-01
  • 打赏
  • 举报
回复
呵呵,刚刚上面说的不对
select控制超时就要将套节字设成异步的

看了一下你的代码
没有数据传输的原因
是否是因为服务器和客户端都在等待对方发数据?
结果大家都在等待

还有,你的client代码是不是有问题
fdWrite对应的应该是send操作
fdRead对应的应该是recv操作
swxlion 2004-09-01
  • 打赏
  • 举报
回复
Client.cpp

#define _WIN32_WINNT 0x0400
#include <windows.h>
#include <stdio.h>
#include <iostream.h>

SOCKET WSListenSocket;
SOCKET WSAcceptSocket;
SOCKET WSWorkSocket;
char WSConnectKey[20];
int WSCodeKey[20];
int WSCodeDefLen;
char WSMLocalIP[16], WSMServerIP[16];
int WSServPort = 2000, WSClientPort = 3000;

int InitWSConnect( void );

int WSMainConnect( );
//**************************************************************
//* InitWSConnect: 初始化网络连接 *
//**************************************************************
int InitWSConnect( void )
// 成功返回0,失败返回-1
{
WORD wVersionRequested = MAKEWORD( 2, 0 );
WSADATA wsaData;
int ErrorCode;
CHAR szHostName[MAX_PATH];
HOSTENT* pHost = NULL;

CHAR* pszIp = NULL;

ErrorCode = WSAStartup( wVersionRequested, &wsaData );
if ( ErrorCode != 0 )
{
return -1;
}

if( gethostname( szHostName, sizeof( szHostName ) ) == 0 )

{
pHost = gethostbyname( szHostName );
if( pHost != NULL )
{
pszIp = inet_ntoa( *( in_addr* )pHost->h_addr_list[0] );
strcpy( WSMLocalIP, pszIp );
// MessageBox(NULL,WSMLocalIP,NULL,NULL);
return 0;
}
}
return -1;
}



/////////////////////////////////////////////////////////////
//
int WSMainConnect( )
// 返回0代表正常关闭连接;返回1代表卸载 WS 系统,返回-1代表重启 WS 系统
{
SOCKADDR_IN servAddr;
struct protoent *WSCProto;
SOCKADDR_IN bindAddr;

char dd[1000];
strcpy(dd,"asdghfghgf");

if( InitWSConnect() == -1 )
{
MessageBox( NULL, "WS网络初始化失败!\n请重试!", NULL, NULL );
return -1;
}

servAddr.sin_family = AF_INET;
servAddr.sin_addr.s_addr = inet_addr( WSMServerIP );
servAddr.sin_port = htons( WSClientPort );

if(servAddr.sin_addr.s_addr == INADDR_NONE)
{
printf("error!\n");
}

bindAddr.sin_family = AF_INET;
bindAddr.sin_addr.s_addr = htonl( INADDR_ANY );
bindAddr.sin_port = htons( WSServPort );

WSCProto = getprotobyname("tcp");
WSWorkSocket = socket( AF_INET, SOCK_STREAM, WSCProto->p_proto );
if( WSWorkSocket == INVALID_SOCKET )
{
closesocket( WSWorkSocket );
return 0;
}
//if ( bind( WSWorkSocket, ( PSOCKADDR )&bindAddr, sizeof( bindAddr ) ) == SOCKET_ERROR )
//{
// closesocket( WSWorkSocket );
// return 0;
//}


if( connect( WSWorkSocket, ( struct sockaddr * )&servAddr, sizeof( servAddr ) ) == SOCKET_ERROR )
{
closesocket( WSWorkSocket );
return 0;
}

unsigned long notBlock = 1;
fd_set fdRead, fdWrite;
struct timeval tv;
char szBuffer[10000];
int ret;

tv.tv_sec = 5;
tv.tv_usec = 0;
//ioctlsocket( WSWorkSocket, FIONBIO, ¬Block );



printf("will send!\n");
while( true )
{


strcpy(dd,"asdghfghgf");
printf("-----------------------------------\n");
// FD_ZERO( &fdRead );
// FD_SET( WSWorkSocket, &fdRead );
// ret = select( 0, &fdRead, NULL, NULL, &tv );
// if( ret == SOCKET_ERROR ) break;
// if( ret > 0 && FD_ISSET( WSWorkSocket, &fdRead ) )
{
ret = send( WSWorkSocket, dd, strlen(dd), 0 );
if( ret == 0 ) break;
if( ret == SOCKET_ERROR ) break;
}


// FD_ZERO( &fdWrite );
// FD_SET( WSWorkSocket, &fdWrite );
// ret = select( 0, NULL, &fdWrite, NULL, &tv );
//if( ret == SOCKET_ERROR ) break;
//if( ret > 0 && FD_ISSET( WSWorkSocket, &fdWrite ) )
{
ret = recv( WSWorkSocket, dd, strlen(dd), 0 );
if( ret == 0 ) break;//return 0;
if( ret == SOCKET_ERROR ) break;
dd[ret] ='\0';
printf("%s\n",dd);
}


}


closesocket( WSWorkSocket );
return 0;
}

int main()
{
cout<<"IP:"<<endl;
cin>>WSMServerIP;
cout<<WSMServerIP<<"++"<<endl;
WSMainConnect( );
return 1;
}
swxlion 2004-09-01
  • 打赏
  • 举报
回复
CS.cpp

#define _WIN32_WINNT 0x0400
#include <windows.h>
#include <stdio.h>
#include <iostream.h>

SOCKET WSListenSocket;
SOCKET WSAcceptSocket;
char WSConnectKey[20];
int WSCodeKey[20];
int WSCodeDefLen;
char WSMLocalIP[16], WSMServerIP[16];
int WSServPort = 2000, WSClientPort = 3000;

int InitWSConnect( void );
int ConnectServ( void );
int ConnectWork( void );
//**************************************************************
//* InitWSConnect: 初始化网络连接 *
//**************************************************************
int InitWSConnect( void )
// 成功返回0,失败返回-1
{
WORD wVersionRequested = MAKEWORD( 2, 0 );
WSADATA wsaData;
int ErrorCode;
CHAR szHostName[MAX_PATH];
HOSTENT* pHost = NULL;

CHAR* pszIp = NULL;

ErrorCode = WSAStartup( wVersionRequested, &wsaData );
if ( ErrorCode != 0 )
{
return -1;
}

if( gethostname( szHostName, sizeof( szHostName ) ) == 0 )

{
pHost = gethostbyname( szHostName );
if( pHost != NULL )
{
pszIp = inet_ntoa( *( in_addr* )pHost->h_addr_list[0] );
strcpy( WSMLocalIP, pszIp );
return 0;
}
}
return -1;
}

//**************************************************************
//* ConnectServ: *
//**************************************************************
int ConnectServ( void )
// 成功返回0,失败返回-1
{
SOCKADDR_IN servAddr, clientAddr;
int AddrSize;
int checkPort = 0;
char *pDestIP, CheckIP[16];
struct protoent *WSCProto;

servAddr.sin_family = AF_INET;
servAddr.sin_addr.s_addr = htonl( INADDR_ANY );/*inet_addr( WSMLocalIP ); */
servAddr.sin_port = htons( WSClientPort );

if( InitWSConnect() == -1 )
{
MessageBox( NULL, "WS网络初始化失败!\n请重试!", NULL, NULL );
return -1;
}
printf("init!\n");
WSCProto = getprotobyname("tcp");
WSListenSocket = socket( AF_INET, SOCK_STREAM, WSCProto->p_proto );
if( WSListenSocket == INVALID_SOCKET )
{
closesocket( WSListenSocket );

return -1;
}
printf("socket!\n");
if( bind( WSListenSocket, ( PSOCKADDR )&servAddr, sizeof( servAddr ) ) == SOCKET_ERROR )
{
closesocket( WSListenSocket );

return -1;
}
printf("bind!\n");
listen( WSListenSocket, 2 );
printf("listen!\n");

while( true )
{
printf("==============================!\n");
AddrSize = sizeof( clientAddr );
WSAcceptSocket = accept( WSListenSocket, ( struct sockaddr * )&clientAddr,&AddrSize );
if( WSAcceptSocket == INVALID_SOCKET )
{
closesocket( WSAcceptSocket );
break;
}
printf("acc 1!\n");
pDestIP = inet_ntoa( clientAddr.sin_addr );
strcpy( CheckIP, pDestIP );
checkPort = ( int )ntohs( clientAddr.sin_port );
goto WSConnectOK;

}
WSConnectOK:
printf("accept!\n");
CreateThread( NULL, 0, ( LPTHREAD_START_ROUTINE )ConnectWork, NULL, 0, NULL );
//--------------------------------------------
WSConnectExit:
Sleep(20000);
return 0;
}

//**************************************************************
//* ConnectWork: 连接应答函数 *
//**************************************************************
int ConnectWork( void )
// 成功返回0,失败返回-1
{

//--------------------------------------------
unsigned long notBlock = 1;
fd_set fdRead, fdWrite;
struct timeval tv;
char szBuffer[10000];
int ret;

tv.tv_sec = 5;
tv.tv_usec = 0;
// ioctlsocket( WSAcceptSocket, FIONBIO, ¬Block );
while( true )
{
printf("----------------------------------------------------!\n");
// FD_ZERO( &fdRead );
// FD_SET( WSAcceptSocket, &fdRead );
// ret = select( 0, &fdRead, NULL, NULL, &tv );
// if( ret == SOCKET_ERROR ) break;
// if( ret > 0 && FD_ISSET( WSAcceptSocket, &fdRead ) )
{
ret = recv( WSAcceptSocket, szBuffer, 10000, 0 );
if( ret == 0 ) break;//goto WSbreakConnect;//break;
if( ret == SOCKET_ERROR ) break;
printf("%s\n",szBuffer);
}
//----------------------------
int nLeft, index;

szBuffer[ret] = '\0';
nLeft = ret;
index = 0;
while( nLeft > 0 )
{
// FD_ZERO( &fdWrite );
// FD_SET( WSAcceptSocket, &fdWrite );
// ret = select( 0, NULL, &fdWrite, NULL, &tv );
// if( ret == SOCKET_ERROR ) break;
// if( ret > 0 && FD_ISSET( WSAcceptSocket, &fdWrite ) )
{
ret = send( WSAcceptSocket, &szBuffer[index], nLeft, 0 );
if( ret == 0 ) break;
if( ret == SOCKET_ERROR ) break;
nLeft -= ret;
index += ret;
}
}
//----------------------------
}
WSbreakConnect:

//--------------------------------------------

closesocket( WSAcceptSocket );
closesocket( WSListenSocket );
return 0;
}
int main()
{
cout<<"Serv Start"<<endl;
ConnectServ();
return 1;
}
swxlion 2004-09-01
  • 打赏
  • 举报
回复
刚才没截好,又删不掉,再截断:
CS.cpp

while( true )
{
accept( ... );
CreateThread( NULL, 0, ( ... )ConnectWork, NULL, 0, NULL );
}
... ...
int ConnectWork( void )
{
... ...
// ioctlsocket( WSAcceptSocket, FIONBIO, ¬Block );
while( true )
{
// FD_ZERO( &fdRead );
// FD_SET( WSAcceptSocket, &fdRead );
// ret = select( 0, &fdRead, NULL, NULL, &tv );
// if( ret == SOCKET_ERROR ) break;
// if( ret > 0 && FD_ISSET( WSAcceptSocket, &fdRead ) )
{
ret = recv( WSAcceptSocket, szBuffer, 10000, 0 );
}
... ...
while( nLeft > 0 )
{
// FD_ZERO( &fdWrite );
// FD_SET( WSAcceptSocket, &fdWrite );
// ret = select( 0, NULL, &fdWrite, NULL, &tv );
// if( ret == SOCKET_ERROR ) break;
// if( ret > 0 && FD_ISSET( WSAcceptSocket, &fdWrite ) )
{
ret = send( WSAcceptSocket, &szBuffer[index], nLeft, 0 );
... ...
}
}
}
... ...
}
... ...

//////////////////////////////
Client.cpp

int WSMainConnect( )
{
... ...
servAddr.sin_addr.s_addr = inet_addr( WSMServerIP );
servAddr.sin_port = htons( WSServPort );

bindAddr.sin_addr.s_addr = htonl( INADDR_ANY );
bindAddr.sin_port = htons( WSClientPort );
... ...
//bind( WSWorkSocket, ( PSOCKADDR )&bindAddr, sizeof( bindAddr ) );
connect(WSWorkSocket,(struct sockaddr *)&servAddr,sizeof(servAddr));
... ...
//ioctlsocket( WSWorkSocket, FIONBIO, ¬Block );
while( true )
{
strcpy(dd,"asdghfghgf");
// FD_ZERO( &fdRead );
// FD_SET( WSWorkSocket, &fdRead );
// ret = select( 0, &fdRead, NULL, NULL, &tv );
// if( ret == SOCKET_ERROR ) break;
// if( ret > 0 && FD_ISSET( WSWorkSocket, &fdRead ) )
{
ret = send( WSWorkSocket, dd, strlen(dd), 0 );
... ...
}
// FD_ZERO( &fdWrite );
// FD_SET( WSWorkSocket, &fdWrite );
// ret = select( 0, NULL, &fdWrite, NULL, &tv );
//if( ret == SOCKET_ERROR ) break;
//if( ret > 0 && FD_ISSET( WSWorkSocket, &fdWrite ) )
{
ret = recv( WSWorkSocket, dd, strlen(dd), 0 );
... ...
}
}
... ...
}
swxlion 2004-09-01
  • 打赏
  • 举报
回复
那好吧,我将代码截断:

CS.cpp

while( true )
{
accept( ... );

CreateThread( NULL, 0, ( ... )ConnectWork, NULL, 0, NULL );

}
... ...
int ConnectWork( void )
{
... ...
// ioctlsocket( WSAcceptSocket, FIONBIO, ¬Block );
while( true )
{

// FD_ZERO( &fdRead );
// FD_SET( WSAcceptSocket, &fdRead );
// ret = select( 0, &fdRead, NULL, NULL, &tv );
// if( ret == SOCKET_ERROR ) break;
// if( ret > 0 && FD_ISSET( WSAcceptSocket, &fdRead ) )
{
ret = recv( WSAcceptSocket, szBuffer, 10000, 0 );
}
... ...
while( nLeft > 0 )
{
// FD_ZERO( &fdWrite );
// FD_SET( WSAcceptSocket, &fdWrite );
// ret = select( 0, NULL, &fdWrite, NULL, &tv );
// if( ret == SOCKET_ERROR ) break;
// if( ret > 0 && FD_ISSET( WSAcceptSocket, &fdWrite ) )
{
ret = send( WSAcceptSocket, &szBuffer[index], nLeft, 0 );
... ...
}
}
}
... ...
}
... ...

//////////////////////////////
Client.cpp

int WSMainConnect( )
{
... ...
servAddr.sin_addr.s_addr = inet_addr( WSMServerIP );
servAddr.sin_port = htons( WSServPort );

bindAddr.sin_addr.s_addr = htonl( INADDR_ANY );
bindAddr.sin_port = htons( WSClientPort );
... ...

//bind( WSWorkSocket, ( PSOCKADDR )&bindAddr, sizeof( bindAddr ) );
connect(WSWorkSocket,(struct sockaddr *)&servAddr,sizeof(servAddr));
... ...
//ioctlsocket( WSWorkSocket, FIONBIO, ¬Block );

while( true )
{
strcpy(dd,"asdghfghgf");
// FD_ZERO( &fdRead );
// FD_SET( WSWorkSocket, &fdRead );
// ret = select( 0, &fdRead, NULL, NULL, &tv );
// if( ret == SOCKET_ERROR ) break;
// if( ret > 0 && FD_ISSET( WSWorkSocket, &fdRead ) )
{
ret = send( WSWorkSocket, dd, strlen(dd), 0 );
... ...
}
// FD_ZERO( &fdWrite );
// FD_SET( WSWorkSocket, &fdWrite );
// ret = select( 0, NULL, &fdWrite, NULL, &tv );
//if( ret == SOCKET_ERROR ) break;
//if( ret > 0 && FD_ISSET( WSWorkSocket, &fdWrite ) )
{
ret = recv( WSWorkSocket, dd, strlen(dd), 0 );
... ...
}
}
... ...
}
msdn_user 2004-09-01
  • 打赏
  • 举报
回复
1 select可以用在阻塞方式中以控制超时
2 这个是设置socket为非阻塞,select模型中不需要socket为非阻塞
3 客户端不需要bind,程序退出的问题可以单步调试,一步步看是哪里出了问题
代码太长了,没耐心看
swxlion 2004-09-01
  • 打赏
  • 举报
回复
这样啊?
那select事做什么用的?我以前在Unix下就是用select(在一个串口驱动,不是网络程序)作的超时控制。
那请问,1.如果要作超时控制,那该怎么办?
2.ioctlsocket( WSWorkSocket, FIONBIO, ¬Block );还需要加上吗?
3.题头三个问题。
谢谢!

18,363

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 网络编程
c++c语言开发语言 技术论坛(原bbs)
社区管理员
  • 网络编程
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

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