8
回答
【求教】如何使用socket的非阻塞模式?
利用AWS快速构建适用于生产的无服务器应用程序,免费试用12个月>>>   

最近在用python研究网络编程,打算写个小服务器。现在有点搞不懂在server端,socket如何使用unblocking模式。之前用写了一个用select.select实现的服务器,如果用unblocing模式,就会报错

这个代码已经分享到http://www.oschina.net/code/snippet_97079_6675

如果把这段代码中2处 setblocking(0) 注释掉,可以正常运行。如果不注释的话,运行很短时间就会报错。

求达人指正。最好附代码

举报
asdfsx
发帖于6年前 8回/1K+阅
共有8个答案 最后回答: 6年前

unblocking 在JAVA和C C++里 是委托给IOChannel去实现的 python没研究过  给你JAVA代码自己看吧

一般分为 多线程阻塞 非阻塞 / 单线程阻塞 /单一线程阻塞 非阻塞这三种 

简单地说 每一个SS请求 serversocket 需要一个字节码缓冲区来读取和写入字节码 然后转换输出文本 理论上可以用一个非常大的buffer区来解决这个问题  但如果是第一种 多线程阻塞模式 一次只能读取规定大小的字节码 而并发连接一旦过多 处理内容过大 就会有严重的内存崩坏 也就是stackoverflow了~ Java1.5以后专门用一个 nio包来处理这个问题 python不了解~  java在NIO包中定义一个selecter类来循环监听SS 判断写入内容是否达到stack顶端  也就是outbonder字节码缓冲区外界 一旦达到外界 就发出一个信号signal 或者直接抛出IO异常  JDK的原话是这么写的: When you reach the end of a input stream

 * via a read() returning -1 or an IOException, we call

 * sslEngine.closeInbound() to signal to the sslEngine that no more

 * input will be available.

 

 *               Application Data

 *               src      requestBB

 *                |           ^

 *                |     |     |

 *                v     |     |

 *           +----+-----|-----+----+

 *           |          |          |

 *           |       SSL|Engine    |

 *   wrap()  |          |          |  unwrap()

 *           | OUTBOUND | INBOUND  |

 *           |          |          |

 *           +----+-----|-----+----+

 *                |     |     ^

 *                |     |     |

 *                v           |

 *            outNetBB     inNetBB

 *                   Net data

其实也很简单 对每一个处理线程的字节码操作上锁 但python本身貌似没有sychronized关键字  所以就不知道怎么操作你要的效果了

public final SelectableChannel configureBlocking(boolean block)

throws IOException

    {

        if (!isOpen())

            throw new ClosedChannelException();

synchronized (regLock) {

   if (blocking == block)

return this;

   if (block && haveValidKeys())

throw new IllegalBlockingModeException();

   implConfigureBlocking(block);

   blocking = block;

}

return this;

    }

非常感谢大家的回复

已经找到正确答案了

python的处理和c的基本一样,调用setblocking(0)以后,要处理系统返回的错误代码 EWOULDBLOCK,EAGAIN

直接上代码

while True:
        r,w,e = select.select(r,w,e,1)
        try:
            ......
        except socket.error,arg:
            (errorno, error_msg) = arg
            if errorno in (errno.EWOULDBLOCK, errno.EAGAIN):
                print "Connect server failed: %s, errno=%d" % (error_msg, errorno)
            else:
                raise

大概是这样

我在尝试用python模拟nginx或者apache,还没有加入进程、线程,先熟悉一下select、poll、epoll、block、unblock

--- 共有 4 条评论 ---
asdfsx@恋恋美食 : r、w、e三个都是数组哦 你可以看我分享的代码,就是上边那个链接 6年前 回复
恋恋美食这个select参数相比C而言少了一个呢?难道python不关心描述字个数? 6年前 回复
Yisen写的差不多可以拿出来分享一下:-) 6年前 回复
asdfsx如果有啥补充的,请继续哈 6年前 回复
python 语言很强大了 写个http服务器 跟玩似的  当然java也只需要 3000K代码以内  TK比SWING强 如果我生在国外  一定学python 而不是java
用twisted吧
--- 共有 1 条评论 ---
asdfsx用twisted也可以.....只不过有时候喜欢究根问底,所以最后还是要探究socket、并发、阻塞的问题,hohoho 6年前 回复
顶部