如何在C语言中判断socket是否已经断开

下面来介绍判断非阻塞SOCKET是否已经断开的几种方法:

注意要区分不同操作系统分别进行测试, 包括WINDOWS, LINUX和UNIX会各有不同。

在WINDOWS下比较简单,可以使用FD_CLOSE事件判断SOCKET是否已经断开

view plaincopy to clipboardprint?
bool IsSocketClosed(SOCKET clientSocket)
{
 bool ret = false;
 HANDLE closeEvent = WSACreateEvent();
 WSAEventSelect(clientSocket, closeEvent, FD_CLOSE); 

 DWORD dwRet = WaitForSingleObject(closeEvent, 0); 

 if(dwRet == WSA_WAIT_EVENT_0)
 ret = true;
 else if(dwRet == WSA_WAIT_TIMEOUT)
 ret = false; 

 WSACloseEvent(closeEvent);
 return ret;
}
 

在UNIX/LINUX下,非阻塞模式SOCKET可以采用recv+MSG_PEEK的方式进行判断,其中MSG_PEEK保证了仅仅进行状态判断,而不影响数据接收

对于主动关闭的SOCKET, recv返回-1,而且errno被置为9(#define EBADF   9 /* Bad file number */)

或104 (#define ECONNRESET 104 /* Connection reset by peer */)

对于被动关闭的SOCKET,recv返回0,而且errno被置为11(#define EWOULDBLOCK EAGAIN /* Operation would block */)

对正常的SOCKET, 如果有接收数据,则返回>0, 否则返回-1,而且errno被置为11(#define EWOULDBLOCK EAGAIN /* Operation would block */)

因此对于简单的状态判断(不过多考虑异常情况),
    recv返回>0,   正常
    返回-1,而且errno被置为11  正常
    其它情况    关闭

view plaincopy to clipboardprint?
#include <errno.h> 

bool IsSocketClosed(int clientSocket)
{
 char buff[32];
 int recvBytes = recv(clientSocket, buff, sizeof(buff), MSG_PEEK); 

 int sockErr = errno; 

 //cout << "In close function, recv " << recvBytes << " bytes, err " << sockErr << endl; 

 if( recvBytes > 0) //Get data
 return false; 

 if( (recvBytes == -1) && (sockErr == EWOULDBLOCK) ) //No receive data
 return false; 

 return true;
}

此外,所有操作系统上还可以通过TCP_KEEPLIVE实行心跳检测

(0)

相关推荐

  • 如何在c语言下关闭socket

    c语言关闭socket的两种方式 一.shutdown() #include<sys/socket.h> int shutdown(int sockfd,int how); how的方式有三种分别是 SHUT_RD(0):关闭sockfd上的读功能,此选项将不允许sockfd进行读操作.不允许接受. SHUT_WR(1):关闭sockfd的写功能,此选项将不允许sockfd进行写操作.不允许发送. SHUT_RDWR(2):关闭sockfd的读写功能.不允许发送和接受(和 close() 一样

  • 如何在C语言中判断socket是否已经断开

    下面来介绍判断非阻塞SOCKET是否已经断开的几种方法: 注意要区分不同操作系统分别进行测试, 包括WINDOWS, LINUX和UNIX会各有不同. 在WINDOWS下比较简单,可以使用FD_CLOSE事件判断SOCKET是否已经断开 view plaincopy to clipboardprint? bool IsSocketClosed(SOCKET clientSocket) { bool ret = false; HANDLE closeEvent = WSACreateEvent()

  • 详解如何在Go语言中调用C源代码

    目录 开坑说明 内嵌形式 外置的C代码 1. 构建libauth.a静态库 2. 对main.go稍加修改 3. 编译 开坑说明 最近在编写客户端程序或与其他部门做功能集成时多次碰到了跨语言的sdk集成,虽说方案很多诸如rpc啊,管道啊,文件io啊,unix socket啊之类的不要太多,但最完美的基础方式还是让程序与sdk结合到一起(个人观点,不喜勿喷),顺便研究了下在go调用标准c接口的种种方法与坑,内容不少,有空便慢慢更新了. 内嵌形式 先让我们来看一个最简单的cgo实例 package

  • C语言中判断两个IPv4地址是否属于同一个子网的代码

    问题描述: 现给定两个IPv4地址,和一个子网掩码,判断是否属于同一个子网,若属于,输出1,否则输出0. 例如输入: 172.16.1.3 172.16.1.35 255.255.255.224 输出: 0 解决方案: 首先将字符串格式的IP地址转化为4字节的IP地址,然后使用与(&)运算,分别将两个IP地址与掩码相与,若最后的值相同,则为同一个子网,否则不是. 以下函数的作用是将字符串格式的IP转化为4字节的IP(因为是4字节,所以使用int,但不同平台的int所占的字节好像不同哈~不太确定)

  • C语言中判断一个char*是不是utf8编码

    C语言中判断一个char*是不是utf8编码 里我修改了一下, 纯ASCII编码的字符串也返回true, 因为UTF8和ASCII兼容 实例代码: int utf8_check(const char* str, size_t length) { size_t i; int nBytes; unsigned char chr; i = 0; nBytes = 0; while (i < length) { chr = *(str + i); if (nBytes == 0) { //计算字节数 i

  • C语言中判断素数(求素数)的思路与方法实例

    目录 前言 思路1实现: 思路2实现: <C与指针>4.14-2: 补充:判断素数的4种方法实例 总结 前言 素数又称质数.所谓素数是指除了 1 和它本身以外,不能被任何整数整除的数,例如17就是素数,因为它不能被 2~16 的任一整数整除. 思路1):因此判断一个整数m是否是素数,只需把 m 被 2 ~ m-1 之间的每一个整数去除,如果都不能被整除,那么 m 就是一个素数. 思路2):判断方法还可以简化.m 不必被 2 ~ m-1 之间的每一个整数去除,只需被 2 ~  之间的每一个整数去

  • 如何在 Go语言中使用日志包

    目录 Go 语言标准库之log 包 如何将日志消息存储在 Go 中的文件中 定制你的日志记录器 总结 引言: 在我们的日常编程中,日志很重要.只要是我们写代码,就有可能出现 Bug.日志文件就是一种快速找到这些 bug,更好地了解程序工作状态的方法. 让我们来看一下日志文件的定义: 日志文件是记录操作系统或其他软件运行中发生的事件或通信软件的不同用户之间的消息的文件.记录是保存日志的行为. 日志是开发人员的眼睛和耳朵,可以用来跟踪.定位错误.调试和分析代码,并监控应用程序的性能.在最简单的情况下

  • 详解如何在Go语言中循环数据结构

    目录 如何在Go中循环字符串 如何在Go中循环map结构 如何在Go中循环Struct 数组是存储类似类型数据的强大数据结构.您可以通过索引识别和访问其中的元素. 在Golang中,您可以通过在0初始化变量i并增加变量直到它达到数组的长度,使用for循环循环数组. 它们的语法如下所示: for i := 0; i < len(arr); i++ { // perform an operation } 例如,让我们循环一个整数数组: package main import ( "fmt&qu

  • C语言中判断int,long型等变量是否赋值的方法详解

    当然,如果你不赋值给局部变量,这样会导致整个程序的崩溃,因为,它的内容被系统指向了垃圾内存.下面我们看一段代码: 复制代码 代码如下: #include <stdio.h>#include <string.h>#include <stdlib.h>int globle_value;int my_sum(int value1, int value2);long my_sub(long value1, long value2);int main(void){ int aut

  • C语言中判断两数组中是否有相同的元素

    思路: 首先创建两个数组,分别为a[ ]和b[ ]先拿a数组里的第一个元素和b数组的所有元素比较是否相同,再拿a数组里的第二个元素与b数组所有元素进行比较,以此类推.运用两次for循环来完成,用i循环生成a数组的各个下标,在循环体中用j循环生成b数组下标,j循环中判断a[ i ]是否等于b[ j ],如果条件成立即相同元素.flag用来标记程序运行到某一刻的状态,来加以判断if中的语句是否执行. system函数的作用是运行以字符串参数的形式传递给他的命令,并且等待该命令的完成,形式:#incl

  • C语言中等待socket连接和对socket定位的方法

    C语言listen()函数:等待连接 头文件: #include <sys/socket.h> 定义函数: int listen(int s, int backlog); 函数说明:listen()用来等待参数s 的socket 连线. 参数backlog 指定同时能处理的最大连接要求, 如果连接数目达此上限则client 端将收到ECONNREFUSED 的错误. Listen()并未开始接收连线, 只是设置socket 为listen 模式, 真正接收client 端连线的是accept(

随机推荐