Socket阻塞模式和非阻塞模式

简介:

       阻塞模式和非阻塞模式

网络不是一个稳定可靠的,存在各种异常情况,比如connect和服务端

三次握手失败,那这个函数就会阻塞,各种问题,可以设置非阻塞,

超时处理,1可以用Socket进行设置,但是考虑到跨平台可能有些函数用不到,   就只能用一种,select多路复用,把socket变成非阻塞模式,

第一步就是把socket设置成非阻塞模式,


        1Windows设置阻塞和非阻塞

1
bool  setBlock( bool  isblock);

有得时候需要阻塞模式,有得时候不需要阻塞模式.主要的目的是

实现超时的控制。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
bool   XTCP::SetBlock( bool  isblock)
{
if  (m_sock <= 0) return  false ;
unsigned  long  ul = 0;
if  (!isblock)
{
//connect 会立刻返回
ul = 1;
}
// FIONBIO 阻塞模式
//ul =0 表示阻塞模式 
//设置模式
ioctlsocket(m_sock, FIONBIO, &ul);
return  true ;
}


测试代码, 发现了就是设置false的时候,connect经过的非常快

一下就返回了,但是设置称true的时候,connect就是阻塞的模式会阻塞

几秒钟.

1
2
3
4
5
6
7
8
9
10
#include "XTCP.h"
int  main( int  argc, char *argv[])
{
XTCP client;
client.CreateSocket();
client.SetBlock( false );
client.Connect( "192.168.1.125" ,846);
getchar ();
return  0;
}

         


        2Linux设置阻塞和非阻塞

Windows和Linux的接口函数又不一样了,

头文件  #include <fcntl.h>


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
bool   XTCP::SetBlock( bool  isblock)
{
     if  (m_sock <= 0) return  false ;
     unsigned  long  ul = 0;
     if  (!isblock)
     {
         //connect 会立刻返回
         ul = 1;
     }
     // FIONBIO 阻塞模式
     //ul =0 表示阻塞模式 
#ifdef WIN32
     ioctlsocket(m_sock, FIONBIO, &ul);
#else
     //操作文件描述法,先获取属性
     int  flags = fcntl(m_sock,F_GETFL,0);
     if  (flags < 0)
         return  false //出错了
     if  (isblock)
     {
             //阻塞模式
             flags = flags &~ O_NONBLOCK;
     }
     else
     {
         //非阻塞模式
         flags = flags | O_NONBLOCK;
     }
     if (fcntl(m_sock, F_SETFL, flags)!=0)
     return  false ;
#endif
 
     return  true ;
}


不过Linux和windows有写不同,是连接的ip存在,但端口不存在

他会立刻反回,所以测试的时候需要把ip改成不存的的测试下.

测试的时候就会发现,false会立刻反回,

他是一个多路复用,不管连接是否成功,放在后端通过select读取

连接信息,这样的话,非阻塞就设置成功


               

          3通过select实现connect跨平台超时处理

重启connect函数,默认我们是1秒钟,

1
bool  Connect( const  char  *ip, unsigned  short  port, int  timeoutms=1000);


定义connect

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
bool  XTCP::Connect( const  char  *ip, unsigned  short  port,  int  timeoutms)
{
//如果socket没有创建
if  (m_sock <= 0) CreateSocket();
//连接需要这个结构体
sockaddr_in saddr;
saddr.sin_family = AF_INET;
saddr.sin_port = htons(port);   //本地字节序转网络字节序
saddr.sin_addr.s_addr = inet_addr(ip);
//改成非阻塞模式
SetBlock( false );
//文件句柄数组  存放文件句柄当前的状态
fd_set set;
//这里会立即反回
if  (connect(m_sock, (sockaddr*)&saddr,  sizeof (saddr)) != 0)
{
//给文件句柄数据 置空
FD_ZERO(&set);
//把socket加到这里面
FD_SET(m_sock, &set);
//通过select监听这个文件序列是否有可读或可写
//第一个参数就是监听的所有文件句柄最大值+1 早windows中可有可无,在linu必须设置
//select是可以监听多个文件句柄的  linux中就是文件描述符
//第二个参数是监听的可读的序列  先用不到
//第三个参数是可写的  set是一组文件描述符列表,只要有其中一个可写,
//select函数就返回 如果没有select本身就是阻塞的 如果
//第四个是一个错误处理
//第五个设置超时时间 是一个结构体
//如果成功反回文件描述符的值   如果失败返回-1  ..超时返回0
timeval  tm ;
tm .tv_sec = 0;  //秒
tm .tv_usec = timeoutms*1000;    //微秒
if  (select(m_sock + 1, 0, &set, 0, & tm ) <= 0)
{
//失败或超时
printf ( "connect timeout or error!\n" );
return  false ;
}
}
//恢复阻塞模式
SetBlock( true );
printf ( "connect %s:%d success!\n" , ip, port);
return  true ;
}

在linux编译测试,

测试代码

执行这个客户端的时候,我们默数3秒,然后accent就反回了,

也是是阻塞超时实现. 3000毫秒也就是3秒 一般情况下500毫秒

连接不是就是网络出问题了,

1
2
3
4
5
6
7
8
9
#include "XTCP.h"
int  main( int  argc, char *argv[])
{
XTCP client;
client.CreateSocket();
client.Connect( "192.168.1.13" ,846,3000);
getchar ();
return  0;
}

效果还是很不错的.



 本文转自超级极客51CTO博客,原文链接:http://blog.51cto.com/12158490/1948229,如需转载请自行联系原作者







相关文章
|
3月前
|
网络协议 NoSQL Linux
非阻塞socket网络编程之数据收发完整代码示例
非阻塞socket网络编程之数据收发完整代码示例
|
5月前
|
网络协议 Python
python socket 阻塞
python socket 阻塞
58 0
|
5月前
|
消息中间件 网络协议 Java
深入剖析阻塞式socket的timeout
深入剖析阻塞式socket的timeout
|
缓存 负载均衡 网络协议
【Socket】两种高效事件处理模式&并发模式
【Socket】两种高效事件处理模式&并发模式
|
XML Java 数据格式
Java,InputStream,Socket阻塞.(关于HTTP请求的IO问题自我总结)
Java,InputStream,Socket阻塞.(关于HTTP请求的IO问题自我总结)
273 0
spring-boot项目整合socket同时启用stomp模式
直接使用WebSocket(或SockJS)就很类似于使用TCP套接字来编写Web应用。因为没有高层级的线路协议(wire protocol),因此就需要我们定义应用之间所发送消息的语义,还需要确保连接的两端都能遵循这些语义。
1740 0
|
12天前
|
安全 Java 数据处理
Python网络编程基础(Socket编程)多线程/多进程服务器编程
【4月更文挑战第11天】在网络编程中,随着客户端数量的增加,服务器的处理能力成为了一个重要的考量因素。为了处理多个客户端的并发请求,我们通常需要采用多线程或多进程的方式。在本章中,我们将探讨多线程/多进程服务器编程的概念,并通过一个多线程服务器的示例来演示其实现。
|
12天前
|
程序员 开发者 Python
Python网络编程基础(Socket编程) 错误处理和异常处理的最佳实践
【4月更文挑战第11天】在网络编程中,错误处理和异常管理不仅是为了程序的健壮性,也是为了提供清晰的用户反馈以及优雅的故障恢复。在前面的章节中,我们讨论了如何使用`try-except`语句来处理网络错误。现在,我们将深入探讨错误处理和异常处理的最佳实践。
|
16天前
|
网络协议 程序员 Python
pythonTCP客户端编程创建Socket对象
【4月更文挑战第6天】本教程介绍了TCP客户端如何创建Socket对象。Socket作为网络通信的基础单元,包含协议、IP地址和端口等信息。在TCP/IP中,Socket分为流式(TCP)、数据报(UDP)和原始套接字。以Python为例,创建TCP Socket对象需调用`socket.socket(AF_INET, SOCK_STREAM)`。为确保健壮性,应使用异常处理处理可能的`socket.error`。学习本教程将帮助你掌握TCP客户端创建Socket对象的技能。