学习 sock 的问题 2

2016-07-13 02:31:46 +08:00
 hard2reg

一直搞不懂这个 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] 你的主机中的软件中止了一个已建立的连接。
3910 次点击
所在节点    Python
9 条回复
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
2016-07-13 05:14:50 +08:00
@paulagent 看完了还是不知哪里错了啊。。
aec4d
2016-07-13 07:35:24 +08:00
socket.recv(maxsize)并不是要接收 maxsize 数据才进行下一步 一有数据就立马执行 最多返回 maxsize 长度数据
当你客户端发送了 exit 自己关闭了连接(非常快吧)
然而你的服务端发送一次暂停一秒 调用 send 对方已经关闭啦 当然报错了
要了解 socket 最好下一本 unix 网络编程 当做字典翻一翻
aec4d
2016-07-13 07:43:19 +08:00
另外你判断是否关闭的逻辑也有问题
你应该使用保存最后接收的三个字符 然后和接收的字符相加 判断是否存在 exit 类似的做法
hard2reg
2016-07-13 09:37:31 +08:00
@aec4d 你的意思是,是这个一秒的延迟导致的?可是我换 1024 就没问题啊
hard2reg
2016-07-13 09:46:41 +08:00
@aec4d 说错了,我是说,换了 1024 就没问题了吗?
gejigeji
2016-07-13 10:01:17 +08:00
1024 是 buffer 长度,你把 buffer 设为 4 , server 端对“ 12345 ”分两次接收, server 端也就发送了两次,导致 client 端接收了两次(即 client 端 s.recv 调用两次),导致循环结束, socket 被 close 掉, server 端再接收就出错了
hard2reg
2016-07-13 11:19:46 +08:00
@gejigeji 懂了谢谢
hard2reg
2016-07-13 23:06:59 +08:00
@gejigeji 如果在 buffer 长度设置足够大的情况下,有没有可能出现这种情况?

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/292104

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX