c语言recv函数返回值,谈谈recv()函数的返回值

网上某论坛有这样一个问题:当recv()函数的返回值为0时,能不能在接收端不关闭套接字,以便这条建立好的C/S通信下次可以直接使用?

我对这个问题的回答是:不能。

原因是:此时即使接收端不关闭套接字,发送端也已经关闭相应的套接字,这条连接需要从accept()/connect()两个函数这里重新建立。

测试代码如下:

#include "stdafx.h"

#include

#include

#pragma comment(lib,"ws2_32")

const int m_listen_port=9923;

#define buff_size 1024

int main(int argc, char* argv[])

{

int ret_common=0;

int ret_error=0;

WSAData wsadata;

WORD m_version;

m_version=MAKEWORD(2,2);

WSAStartup(m_version,&wsadata);

SOCKET

m_server_sock=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);

if (m_server_sock==INVALID_SOCKET)

{

ret_error=WSAGetLastError();

printf("error for

socket() and caputre error code: %d\n",ret_error);

return 0;

}

SOCKADDR_IN m_sock_addr;

memset(&m_sock_addr,0,sizeof(m_sock_addr));

m_sock_addr.sin_family=AF_INET;

m_sock_addr.sin_addr.S_un.S_addr=INADDR_ANY;

m_sock_addr.sin_port=htons(m_listen_port);

ret_common=bind(m_server_sock,(SOCKADDR*)&m_sock_addr,sizeof(m_sock_addr));

if (ret_common==SOCKET_ERROR)

{

ret_error=WSAGetLastError();

printf("error for

bind() and caputre error code: %d\n",ret_error);

return 0;

}

listen(m_server_sock,SOMAXCONN);

fd_set fd_socket;

FD_ZERO(&fd_socket);

FD_SET(m_server_sock,&fd_socket);

while (1)

{

fd_set

fd_read=fd_socket;

ret_common=select(0,&fd_read,NULL,NULL,NULL);

if

(ret_common>0)

{

for

(unsigned int i=0;i

{

BOOL

m_boolen_ret=FD_ISSET(fd_socket.fd_array[i],&fd_read);

if

(m_boolen_ret)

{

if

(fd_socket.fd_array[i]==m_server_sock)

{

SOCKADDR_IN

m_client_addr;

memset(&m_client_addr,0,sizeof(m_client_addr));

int

m_client_addr_len=sizeof(m_client_addr);

SOCKET

m_client_sock=accept(m_server_sock,(SOCKADDR*)&m_client_addr,&m_client_addr_len);

printf("accpet

a connection from socket %d\n",m_client_sock);

FD_SET(m_client_sock,&fd_socket);

}

else

{

char

m_recv_buff[buff_size];

memset(m_recv_buff,0,buff_size);

ret_common=recv(fd_socket.fd_array[i],m_recv_buff,sizeof(m_recv_buff),0);

if

(ret_common>0)// 接收数据包正常,数据包中的数据大于0个字节;

{

printf("receive

data \"%s\" from socket

%d\n",m_recv_buff,fd_socket.fd_array[i]);

continue;

}

else

if

(ret_common==0)// 传输数据包操作完成,连接断开(gracefully);

{

ret_error=WSAGetLastError();

printf("there

is a connection is gracefully closed and capture error code:

%d,socket:%d\n",

ret_error,fd_socket.fd_array[i]);

closesocket(fd_socket.fd_array[i]);

FD_CLR(fd_socket.fd_array[i],&fd_socket); continue;

}

else//

传输数据包出错;

{

ret_error=WSAGetLastError();

closesocket(fd_socket.fd_array[i]);

FD_CLR(fd_socket.fd_array[i],&fd_socket);

if

(ret_error==10054)// 连接被强制断开;

{

printf("client

closed the connection by force, test ret_common:

%d,socket:%d\n",

ret_error,ret_common,fd_socket.fd_array[i]);

}

else//

输出其它错误;

{

printf("error

for recv(), capture error code: %d, test ret_common:

%d,socket:%d\n",

ret_error,ret_common,fd_socket.fd_array[i]);

} continue;

}

}

}

} }

else

{

ret_error=WSAGetLastError();

printf("error

for select() and capture error code: %d\n",ret_error);

break;

}

}

closesocket(m_server_sock);

WSACleanup();

return 0;

}

这段发送端代码不是我写的,看起来可能比较乱,请见谅:

for (int i=0;i<10;i++)

{

strncpy(m_send_buff,"data",sizeof("data"));

char a[20];

memset(a,0,20);

itoa(i+1,a,10);

strncat(m_send_buff,a,20);

ret_common=send(s,m_send_buff,sizeof(m_send_buff),0);

if

(ret_common==SOCKET_ERROR)

{

ret_error=WSAGetLastError();

printf("error

for send() and capture error code: %d\n",ret_error);

break;

}

else

{

printf("send

data: %s\n",m_send_buff);

}

Sleep(1000);

}

Sleep(6000);

// 关闭套节字

::closesocket(s);

Sleep(10000);

printf("ret\n");

return 0;

当包含这段代码的程序发送数据包到包含上一段代码的程序时,发送数据完毕,在等6秒钟后发送数据的套接字才关闭,而接收端也是等6秒钟才输出客户端关闭(gracefully)关闭的信息,再等10描述,发送数据的程序才推出。

总结一下:

(1)当接收端被强行关闭时,ret_common为-1,WSAGetLastError()返回值(即ret_error)为10054(0x2746);

(2)当数据传输执行closesocket()(closesocket()参数为发送数据的套接字)之后,接收端的返回值(即ret_common)为0。

(3)在传输过程中,如果接收端被强行关闭,那么发送端的send()函数的返回值(即ret_common)为-1,WSAGetLastError()的返回值(即ret_error)为10054(0x2746)。

需要注意一点:

WSAGetLastError()的返回值:10054,与GetLastError()的返回值:0x2746,这两个错误返回值是相等的(不同的是针对WSAGetLastError()函数和GetLastError()函数的返回值类型不同(WSAGetLastError()返回int类型操作数;GetLastError()返回DWORD类型操作数))。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值