网上某论坛有这样一个问题:当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类型操作数))。

c语言recv函数返回值,谈谈recv()函数的返回值相关推荐

  1. mysql linux 函数返回值_linux recv函数返回值分析

    函数原型: ssize_t recv(int sockfd, void *buf, size_t len, int flags); 该函数第一个参数制定接收端套接字描述符; 第二个参数指明一个缓冲区, ...

  2. C语言基础入门48篇_20_函数入门:为什么使用函数?(函数使得程序模块化 使用函数封装细节,使得程序员只要面向函数的接口编程(参数与返回值),而不用关心函数内部细节)

    菜鸟和高手都会基本,那菜鸟为什么是菜鸟,高手为什么是高手呢?很大的区别在于,高手写的程序[结构性]更好,更容易维护.而函数就是C语言结构化的一种手段. 函数可以将大的计算任务划分为多个较小的任务(解耦 ...

  3. smali语言详解之一般/构造方法(函数)的声明与返回值关键字

    smali语言详解之一般/构造方法(函数)的声明与返回值关键字 一. smali语言的方法声明格式 .method与.end method成对出现,类似于java中的花括号 1.1.非静态的一般方法 ...

  4. c语言函数返回值类型必须,C++中函数类型与定义的函数返回值类型必须相同么?...

    C++中函数类型与定义的函数返回值类型必须相同么?以下文字资料是由(历史新知网www.lishixinzhi.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧! C++中函数类型与定义 ...

  5. c语言调用oracle函数返回值吗,C语言通过值和引用函数

    . 将参数值或数据传递给C语言函数有两种方法:通过值调用和通过引用调用.原始值在通过值调用时不修改,但通过引用调用时,在函数中可进行修改. 下面将分别讲解如何通过值调用和通过引用调用,并用使用示例逐个 ...

  6. c语言字符串作为函数返回值的类型,返回字符串类型的函数怎么写?

    该楼层疑似违规已被系统折叠 隐藏此楼查看此楼 描述 请判断一个数是不是水仙花数. 其中水仙花数定义各个位数立方和等于它本身的三位数. 输入 有多组测试数据,每组测试数据以包含一个整数n(100< ...

  7. Go 学习笔记(61)— Go 高阶函数、函数作为一等公民(函数作为输入参数、返回值、变量)的写法

    函数在 Go 语言中属于"一等公民(First-Class Citizen)"拥有"一等公民"待遇的语法元素可以如下使用 可以存储在变量中: 可以作为参数传递给 ...

  8. Python 函数参数有冒号 声明后有- 箭头 返回值注释 参数类型注释

    在python3.7 环境下 函数声明时能在参数后加冒号,如图: 1 def f(ham: str, eggs: str = 'eggs') -> str : 2 print("Ann ...

  9. php 函数返回值mixed,认识函数的类型、参数与返回值

    函数的类型.参数与返回值 一.函数的基本语法语法 functionfunctionName(类型限定参数列表):返回值类型 { } 案例:计算两个数之和. functionsum(int$a,int$ ...

最新文章

  1. Spring入门简介
  2. Godaddy如何导入导出MSSQL数据库
  3. 在Windows2012R2中如何安装IIS8.5
  4. 几百个Android开源个性化控件、工具库、项目、开发工具快快收藏
  5. docker知识总结
  6. Linux系统通过FTP进行文档基本操作【华为云分享】
  7. python进程间通信总结_进程间通信方式总结(优缺点)
  8. 【Zookeeper学习】Apache Zookeeper项目简介
  9. STP-2-三个选择
  10. sql替换字符串中的部分字符
  11. 手机三十分钟熄屏如何一直亮_如何让手机屏幕常亮
  12. 【分享】测试小白如何测试手机整机系统测试
  13. HDU - 5977 Garden of Eden (树形dp+容斥)
  14. 2016年上半年系统集成中项4月6日作业
  15. 湖北经济学院法商学院计算机分数线,湖北经济学院法商学院2018年各省及各专业录取分数线及最低录投档线【理科 文科】...
  16. MapServer 7.0.3 Documentation 翻译
  17. 北京哪里可以买到含羞草啊?或者种子也行
  18. 大型电商网站:第一章:主要电商模式
  19. Liferay中的workflow
  20. mysql实现统计查询_MySQL 统计查询实现代码

热门文章

  1. httos双向认证配置_HTTPS双向验证,如何设置
  2. VTK修炼之道52:图形基本操作进阶_多分辨率策略(模型抽取的三种方法)
  3. Uncaught TypeError: Object #Document has no method 'load'
  4. 注入工具的原理和开发
  5. 传智C++课程笔记-1
  6. 基于STM32,无人船岸基信息处理代码--python实现
  7. 如何通过JavaScript动态加载js
  8. jsp里面声明了utf-8格式,也写了字符编码过滤器,数据库编码也是utf-8,就连java.......
  9. 第15章习题解答(二)——《x86汇编语言:从实模式到保护模式》读书笔记41
  10. 【unix时间戳小示例】linux/unix系统获取unix时间戳