V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
Learn Python the Hard Way
Python Sites
PyPI - Python Package Index
http://diveintopython.org/toc/index.html
Pocoo
值得关注的项目
PyPy
Celery
Jinja2
Read the Docs
gevent
pyenv
virtualenv
Stackless Python
Beautiful Soup
结巴中文分词
Green Unicorn
Sentry
Shovel
Pyflakes
pytest
Python 编程
pep8 Checker
Styles
PEP 8
Google Python Style Guide
Code Style from The Hitchhiker's Guide
hard2reg
V2EX  ›  Python

学习 sock 的问题 2

  •  
  •   hard2reg · 2016-07-13 02:31:46 +08:00 · 3991 次点击
    这是一个创建于 3090 天前的主题,其中的信息可能已经有所发展或是发生改变。

    一直搞不懂这个 sock.recv()有什么用,在实践中该怎么规定大小。于是我自作聪明的把 1024 改为了 4 。然后我就贴代码了。

    client.py
    
    # -*- coding: utf-8 -*-
    
    import socket
    
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.connect(('127.0.0.1', 9999))
    print(s.recv(1024).decode('utf-8'))
    for data in [b'12345', b'67890']:
    	s.send(data)
    	print(s.recv(1024).decode('utf-8'))
    s.send(b'exit')
    s.close()
    
    Output
    
    Welcome!
    Hello, 1234!
    Hello, 5!
    
    server.py
    
    # -*- coding: utf-8 -*-
    
    import socket, threading, time
    
    def tcplink(sock, addr):
    	print('Accept new connection from %s:%s' % addr)
    	sock.send(b'Welcome!')
    	while True:
    		data = sock.recv(4)
    		time.sleep(1)
    		if not data or data.decode('utf-8') == 'exit':
    			break
    		sock.send(('Hello, %s!' % data.decode('utf-8')).encode('utf-8'))
    	sock.close()
    	print('Connection from %s:%s closed' % addr)
    
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.bind(('127.0.0.1', 9999))
    s.listen(5)
    print('Waiting for connection')
    while True:
    	sock, addr = s.accept()
    	t = threading.Thread(target=tcplink, args=(sock, addr))
    	t.start()
    
    Output
    
    Waiting for connection
    Accept new connection from 127.0.0.1:59877
    Exception in thread Thread-1:
    Traceback (most recent call last):
      File "D:\Program Files\Python35\lib\threading.py", line 914, in _bootstrap_inner
        self.run()
      File "D:\Program Files\Python35\lib\threading.py", line 862, in run
        self._target(*self._args, **self._kwargs)
      File "C:\Users\xxxx\Desktop\server.py", line 9, in tcplink
        data = sock.recv(4)
    ConnectionAbortedError: [WinError 10053] 你的主机中的软件中止了一个已建立的连接。
    
    9 条回复    2016-07-13 23:06:59 +08:00
    paulagent
        1
    paulagent  
       2016-07-13 05:06:17 +08:00
    socket.recv(bufsize[, flags])
    Receive data from the socket. The return value is a string representing the data received. The maximum amount of data to be received at once is specified by bufsize. See the Unix manual page recv(2) for the meaning of the optional argument flags; it defaults to zero.

    Note For best match with hardware and network realities, the value of bufsize should be a relatively small power of 2, for example, 4096.
    hard2reg
        2
    hard2reg  
    OP
       2016-07-13 05:14:50 +08:00
    @paulagent 看完了还是不知哪里错了啊。。
    aec4d
        3
    aec4d  
       2016-07-13 07:35:24 +08:00
    socket.recv(maxsize)并不是要接收 maxsize 数据才进行下一步 一有数据就立马执行 最多返回 maxsize 长度数据
    当你客户端发送了 exit 自己关闭了连接(非常快吧)
    然而你的服务端发送一次暂停一秒 调用 send 对方已经关闭啦 当然报错了
    要了解 socket 最好下一本 unix 网络编程 当做字典翻一翻
    aec4d
        4
    aec4d  
       2016-07-13 07:43:19 +08:00
    另外你判断是否关闭的逻辑也有问题
    你应该使用保存最后接收的三个字符 然后和接收的字符相加 判断是否存在 exit 类似的做法
    hard2reg
        5
    hard2reg  
    OP
       2016-07-13 09:37:31 +08:00
    @aec4d 你的意思是,是这个一秒的延迟导致的?可是我换 1024 就没问题啊
    hard2reg
        6
    hard2reg  
    OP
       2016-07-13 09:46:41 +08:00
    @aec4d 说错了,我是说,换了 1024 就没问题了吗?
    gejigeji
        7
    gejigeji  
       2016-07-13 10:01:17 +08:00
    1024 是 buffer 长度,你把 buffer 设为 4 , server 端对“ 12345 ”分两次接收, server 端也就发送了两次,导致 client 端接收了两次(即 client 端 s.recv 调用两次),导致循环结束, socket 被 close 掉, server 端再接收就出错了
    hard2reg
        8
    hard2reg  
    OP
       2016-07-13 11:19:46 +08:00
    @gejigeji 懂了谢谢
    hard2reg
        9
    hard2reg  
    OP
       2016-07-13 23:06:59 +08:00
    @gejigeji 如果在 buffer 长度设置足够大的情况下,有没有可能出现这种情况?
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1614 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 33ms · UTC 16:50 · PVG 00:50 · LAX 08:50 · JFK 11:50
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.