send阻塞

socket recv send接口阻塞,会导致服务器端不在响应客户端任何请求,所以一般情况, 会将socket设置为非阻塞状态,

但是有些场景,例如ssl_accept就需要使用阻塞的socket,否则握手极容易失败, 但是一直阻塞,容易导致服务器端DOS现象。

下面是阻塞的解释 http://blog.csdn.net/xiaofei0859/article/details/6037814

比如你调用send函数发送一定的Byte,在系统内部send做的工作其实只是把数据传输(Copy)到TCP/IP协议栈的输出缓冲区,它执行成功并不代表数据已经成功的发送出去了,如果TCP/IP协议栈没有足够的可用缓冲区来保存你Copy过来的数据的话...这时候就体现出阻塞和非阻塞的不同之处了:对于阻塞模式的socket send函数将不返回直到系统缓冲区有足够的空间把你要发送的数据Copy过去以后才返回,而对于非阻塞的socket来说send会立即返回WSAEWOULDDBLOCK告诉调用者说:"发送操作被阻塞了!!!你想办法处理吧..."
对于recv函数,同样道理,该函数的内部工作机制其实是在等待TCP/IP协议栈的接收缓冲区通知它说:嗨,你的数据来了.对于阻塞模式的socket来说如果TCP/IP协议栈的接收缓冲区没有通知一个结果给它它就一直不返回:耗费着系统资源....对于非阻塞模式的socket该函数会马上返回,然后告诉你:WSAEWOULDDBLOCK---"现在没有数据,回头在来看看"

recv阻塞构造方法

服务器端调用recv接口,如果读取不到内容,则进入阻塞状态,进程则处于阻塞状态。

对于ssl_accept会调用recv接口,要求读取一定长度内容,长度大于1,读取内容不够,则进入阻塞状态,

于是可以构造客户端脚本,建立连接后,发送一个字节后, 就开始读取内容,这样与服务器端recv形成死锁,

客户端等待服务器端发送数据, 服务器端由于读取内容不够,则阻塞等待接受内容。

lua socket脚本:

socket = require "socket"
print(socket._VERSION) local address = "192.168.1.1"
local port =
local client = assert (socket.connect(address, port)) if nil ~= client then
client:send("")
print("send to receive !!!!")
local r = client:receive("*a") client:close()
end

send阻塞构造方法

服务器端,调用send接口发送数据,当缓冲中没有足够大的空间,则send接口处于阻塞状态,

等待缓冲区的数据被发送后,缓存的空间可以存储send要发送的数据,则send则激活返回。

客户端发送到client hello数据(ssl握手)后,服务器端会向客户端发送数据,循环发送大概到一M数据,但是客户端不接收,执行sleep操作:

下面lua脚本代码,实现客户端,其中准备clienthello数据,使用str2bin方法,客户端不接收数据,使用sleep休眠三六零零秒。

socket = require "socket"
print(socket._VERSION) local address = "192.168.1.1"
local port =
local client = assert (socket.connect(address, port)) -- http://m.oschina.net/blog/220844
local function bin2hex(s)
s=string.gsub(s,"(.)",function (x) return string.format("%02X ",string.byte(x)) end)
return s
end local h2b = {
[""] = ,
[""] = ,
[""] = ,
[""] = ,
[""] = ,
[""] = ,
[""] = ,
[""] = ,
[""] = ,
[""] = ,
["A"] = ,
["B"] = ,
["C"] = ,
["D"] = ,
["E"] = ,
["F"] =
} local function hex2bin( hexstr )
local s = string.gsub(hexstr, "(.)(.)", function ( h, l )
print( "h="..h.." l="..l )
-- http://www.cnblogs.com/whiteyun/archive/2009/08/07/1540899.html
h = string.upper(h)
l = string.upper(l)
return string.char(h2b[h]*+h2b[l])
end)
return s
end -- http://www.cnblogs.com/wcong/p/3218053.html
require("socket")
function Sleep(n)
socket.select(nil, nil, n)
end local clientHelloHexStr = [[1603010200010001fc0301d836e6926224b009080b70496a6515b8cf5a09603e6e309f400ab79fb67225cc203ca2eda02bb49abb6f6dc513684b5df3cc654268108054fe7e28299b03e6bae0002ec02bc02fc00ac009c013c014c012c007c0110033003200450039003800880016002f004100350084000a0005000401000185ff01000100000a00080006001700180019000b00020100002300a02f1b88ca8fe2638f5d0ae18ed18838f3a4bd7115a8001aeb5dd6a57d825bf06e98c499eb43763091da9ae0baee573c6ba838b33bf8c4ccf96aff04a1aef0b73a8fb17ba2c1af3bd8a65ef8ff3c90d8f6279139e1cae33761420cb8daf0d244ad8ca5c0683b442cabafc41463dd23f2365a89ac75856ce6b0e6c224eda9479142f561a8574381667e2a9cafede019ba213cfbfdca7fa8de776d5e8ba833d2572d33740000001500c20000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000]]
local cleintHelloBlock = hex2bin(clientHelloHexStr); if nil ~= client then
client:send(cleintHelloBlock)
print("send to receive !!!!")
--local r = client:receive("*a")
--print("r="..r)
Sleep()
print("after Sleep")
client:close()
end

服务器端代码,是否能毕现,可调整i的上限尝试:

int i=;
char buff[] = "xxx..xxx" //1034字节
for (;i<;i++)
{
send(fd, buff, , )
}

阻塞避免方法

一种方法就是设置socket为非阻塞模式,此方法最直接

但是有些情况不能接受,例如ssl_accept, 于是有第二种方法,摘自他人博客,设置socket读取或者发送阻塞超时时间。

http://idsips.blog.163.com/blog/static/4800127220116611500538/

linux:

    struct timeval timeout={,};//3s

    int ret=setsockopt(sock_fd,SOL_SOCKET,SO_SNDTIMEO,&timeout,sizeof(timeout));

    int ret=setsockopt(sock_fd,SOL_SOCKET,SO_RCVTIMEO,&timeout,sizeof(timeout));

    如果ret== 则为成功,-1为失败,这时可以查看errno来判断失败原因

    int recvd=recv(sock_fd,buf,,);

    if(recvd==-&&errno==EAGAIN)

   {

              printf("timeout\n");

   }

一种构造WEB服务器端recv和send接口阻塞现象的方法的更多相关文章

  1. UNIX网络编程-recv、send、read、write之间的联系与区别

    1.read ----------------------------------------------------------------------- #include <unistd.h ...

  2. 几种常见web攻击手段及其防御方式

    XSS(跨站脚本攻击) CSRF(跨站请求伪造) SQL注入 DDOS web安全系列目录 总结几种常见web攻击手段极其防御方式 总结几种常见的安全算法 XSS 概念 全称是跨站脚本攻击(Cross ...

  3. 总结几种常见web攻击手段及其防御方式

    本文简单介绍几种常见的攻击手段及其防御方式 XSS(跨站脚本攻击) CSRF(跨站请求伪造) SQL注入 DDOS web安全系列目录 总结几种常见web攻击手段极其防御方式 总结几种常见的安全算法 ...

  4. JWT(Json Web Token):一种在Web应用中安全传递信息的规范 转载

    文本将介绍一种在Web应用中安全传递信息的方式,称为JWT. 本文内容是对JWT官网介绍说明的英文翻译而来,由于本文英文水平有限,如有错误,还请指出,谢谢. What is JSON Web Toke ...

  5. 小测几种python web server的性能

    http://blog.csdn.net/raptor/article/details/8038476 因为换了nginx就不再使用mod_wsgi来跑web.py应用了,现在用的是gevent-ws ...

  6. 两种构造 String 的方法效率比较

    直接上代码吧: package mm_test; /** * @Function: TODO ADD FUNCTION. <br/> * @Date: 2016年4月14日 下午8:25: ...

  7. UNIX网络编程读书笔记:recv和send函数

    这两个函数类似于标准的read和write函数,不过需要一个额外的参数. #include <sys/socket.h> ssize_t recv(int sockfd, void *bu ...

  8. Web服务器端程序的实现

    Web服务器端程序主要是两个部分,一部分是主函数,一部门是命令处理函数.命令处理函数比较好理解就是针对客户端不同的命令进行处理,与客户端进行通信.主函数也有两个主要的功能,第一是要对程序进行初始化,其 ...

  9. java web 服务器端处理json格式参数

    前面我们说了传递参数的两种访书,第一是key-value形式,第二是json格式,对于第一种我们在服务器端直接使用 request.getParameter("key");就能获取 ...

随机推荐

  1. 洛谷 P1144 最短路计数 Label:水

    题目描述 给出一个N个顶点M条边的无向无权图,顶点编号为1-N.问从顶点1开始,到其他每个点的最短路有几条. 输入输出格式 输入格式: 输入第一行包含2个正整数N,M,为图的顶点数与边数. 接下来M行 ...

  2. [深入浅出WP8.1(Runtime)]应用实例——移动截图

    10.2应用实例——移动截图 移动截图例子是实现一个把一张图片的某个部分截取出来的功能,并且用户可以选定截取的图片区间.那个该例子会使用ManipulationDelta事件来实现对截取区间的选择.然 ...

  3. 【BZOJ】1532: [POI2005]Kos-Dicing

    题意 \(n\)个人\(m\)场比赛\((1 \le n \le 10000, 0 \le m \le 10000)\),给出每场比赛的两个选手,求赢得最多的人最少赢的场数. 分析 二分最多人赢的场数 ...

  4. Jquery_jquery中attr和prop的区别

    在高版本的jquery引入prop方法后,什么时候该用prop?什么时候用attr?它们两个之间有什么区别?这些问题就出现了. 关于它们两个的区别,网上的答案很多.这里谈谈我的心得,我的心得很简单: ...

  5. FMS直播流发布时 Microphone Speex 编码设置注意事项

    1.为何要用 Speex?FP的默认音频编码是 NellyMoser,而FP10之后加入了 Speex.实际应用中,用默认的 NellyMoser 编码音频,会有个很大的问题,就是无法控制流码率浮动. ...

  6. JS 弹出模态窗口解决方案

    最近在项目中使用弹出模态窗口,功能要求: (1)模态窗口选择项目 (2)支持选择返回事件处理 在IE中有showModalDialog 方法,可以很好的解决该问题,但是在Chrome中和FF中就有问题 ...

  7. GO语言练习:for基本用法

    1.代码 2.运行 1.代码 package main import "fmt" func main(){ ; k < ; k++{ JLoop: ; j < ; j+ ...

  8. WinForm上显示gif动画:转

    WinForm上的ProgressBar,老实说,实在是不敢恭维,太死板,太难看了,即使做成实时显示处理进度的,它还是逃离不了“难看”.现 在的web2.0上到处都能看到一个显示正在处理的小圆圈在那转 ...

  9. Java开发搜索引擎爬虫

    package com.peidon.html; import java.io.BufferedReader; import java.io.File; import java.io.FileOutp ...

  10. stdout( 标准输出流)和 stderr( 标准输入流) 重定向问题

    我想把提示信息和错误信息列表都写入到同一个文件里, /* ** 设置流, 使输出与错误流都指向指定的文件 */ if( (output1 = freopen( PATH, "a", ...