为什么这个 client 端的 socket 收不到 server 发来的信息?

2018-02-23 09:20:47 +08:00
 woshichuanqilz

下面是代码, server 端会在 recv 上挂住 这个是为什么?

server:

# -*- coding: UTF-8 -*-

# 导入库
import socket, threading, os, uuid, sys

SIZE = 1024 * 1024 * 5
filename = str(uuid.uuid4()) + '.jpg'

# 检查当前目录下是否有等下要命名的图片,有的话删除之
def checkFile():
    list = os.listdir('.')
    for iterm in list:
        if iterm == filename:
            os.remove(iterm)
            print('remove')
        else:
            pass

# 接受数据线程
def tcplink(sock, addr):
# def tcplink():
    print('Accept new connection from %s:%s...' % addr)
    # sock.send(b'Welcome from server!')
    print('receiving, please wait for a second ...')
    while True:
        try:
            data = sock.recv(SIZE)
            if not data :
                print('reach the end of file')
                break
            elif data == 'begin to send':
                print('create file')
                checkFile()
                with open(filename, 'wb') as f:
                    pass
            else:
                with open(filename, 'ab') as f:
                    f.write(data)
        except:
            print("Unexpected error:", sys.exc_info()[0])
            break
    print('msg send')
    sock.send(b'Welcome from server!')
    sock.close()
    print('receive finished')
    print('Connection from %s:%s closed.' % addr)


# 创建一个 socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 监听端口(这里的 ip 要在不同的情况下更改)
s.bind(('127.0.0.1', 9999))
# 每次只允许一个客户端接入
s.listen(2)
print('Waiting for connection...')
while True:
    # 建立一个线程用来监听收到的数据
    sock, addr = s.accept()
    t = threading.Thread(target = tcplink, args = (sock, addr))
    # 线程运行
    t.start()

client:

# -*- coding: UTF-8 -*-
import socket

SIZE = 1024 * 1024 * 5

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 建立连接:
s.connect(('127.0.0.1', 9999))

# 接收欢迎消息:
with open('./image.png', 'rb') as f:
   data = f.read()
   s.sendall(data)

print('sended !')
data = s.recv(SIZE)
# print(data)

s.close()
print('connection closed')

4111 次点击
所在节点    Python
10 条回复
opengps
2018-02-23 09:36:32 +08:00
可惜我不懂你的语言,回答不规范,我看着问题像是 while True 内部那里,没有启用单独的线程处理啊,这样的话,你服务端没法接收并发消息的
heimeil
2018-02-23 09:41:14 +08:00
不知道是不是没收到 welcome,你仔细看看 server 在 send welcome 之前就 while True 了
coderwang
2018-02-23 09:49:21 +08:00
f.write(data) 之后 break
j0hnj
2018-02-23 09:55:06 +08:00
客户端 sendall 之后就把 socket shutdown 吧,这样服务端的 recv 才会收到 EOF 返回,不然就卡住了。或者也可以像 HTTP 一样加一个 content-length 字段
j0hnj
2018-02-23 10:18:12 +08:00
具体一下就是客户端在 sendall 之后应该 s.shutdown(socket.SHUT_WR) 关闭自己的写端
linyinma
2018-02-23 10:23:07 +08:00
这边有几个问题:
( 1 )首先检查./image.png 文件是否存在(文件大小,是否是空文件);
( 2 )
data = sock.recv(SIZE)
if not data :
print('reach the end of file')
这不是文件发送完的意思,是代表对方关闭了 socket,你不能这样写;

( 3 ) TCP 流你无法确定应用层报文是否发送完整,你需要定义一套应用层协议,比如定义头两个字节表示文件长度,服务端先读两个字节判断应用层报文大小,然后读完整个报文~~
woshichuanqilz
2018-02-23 11:30:37 +08:00
@coderwang 你好 确实是 break 哪里的问题加上就好了, 能简单解释下为什么吗? 谢谢~
coderwang
2018-02-23 11:59:49 +08:00
@woshichuanqilz 不 break 循环不会中断,一直卡在 receive
woshichuanqilz
2018-02-23 13:02:50 +08:00
@j0hnj shutdown 之后后面的 server 要发的东西就发不出去了。
j0hnj
2018-02-23 13:39:00 +08:00
@woshichuanqilz #9 TCP 是全双工的,客户端关闭写端,但是仍然可以读取服务端的响应,我这边测试是没问题的

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

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

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

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

© 2021 V2EX