首页 > 解决方案 > Python - 如何通过 socket.makefile 执行套接字通信?

问题描述

基于对这篇文章的最高评价:

套接字:python中的2路通信

和码头:

https://docs.python.org/3/library/socket.html#targetText=socket.makefile

我正在尝试弄清楚如何使用socket.makefile通过套接字发送/接收。这是我到目前为止所拥有的:

服务器.py:

# Server.py

import socket

# module-level variables
HOST='127.0.0.1'
PORT=65439

ACK_TEXT = 'text_received'


def main():
    # instantiate a socket object
    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    print('socket instantiated')

    # bind the socket
    sock.bind((HOST, PORT))
    print('socket binded')

    # start the socket listening
    sock.listen(10)
    print('socket now listening')

    # accept the socket response from the client, get the connection object
    conn, addr = sock.accept()              # Note: execution waits here until the client calls sock.connect()
    print('socket accepted, got connection object')

    sockFile = sock.makefile()

    while True:
        message = sockFile.readline()
        print('received: ' + str(message))
    # end while
# end main

if __name__ == '__main__':
    main()

客户端.py:

# Client.py

import socket
import time

# module-level variables
HOST='127.0.0.1'
PORT=65439

ACK_TEXT = 'text_received'


def main():
    # instantiate a socket object
    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    print('socket instantiated')

    # connect the socket
    sock.connect((HOST, PORT))    # Note: if execution gets here before the server starts up, this line will cause a crash
    print('socket connected')

    sockFile = sock.makefile(mode='w')

    myCounter = 0
    while True:
        message = 'message ' + str(myCounter)
        print('sending: ' + message)

        sockFile.write(message)

        myCounter += 1
        time.sleep(1)       # wait for 1 sec before sending next text message
    # end while
# end main

if __name__ == '__main__':
    main()

现在,如果我启动服务器,然后从单独的命令提示符启动客户端,客户端似乎正在工作:

客户端.py 输出:

$ python3 Client.py 
socket instantiated
socket connected
sending: message 0
sending: message 1
sending: message 2
sending: message 3
sending: message 4
sending: message 5

但服务器因错误而失败:

$ python3 Server.py 
socket instantiated
socket binded
socket now listening
socket accepted, got connection object
Traceback (most recent call last):
  File "Server.py", line 38, in <module>
    main()
  File "Server.py", line 32, in main
    message = sockFile.readline()
  File "/usr/lib/python3.6/socket.py", line 586, in readinto
    return self._sock.recv_into(b)
OSError: [Errno 107] Transport endpoint is not connected

使用时如何在服务器上成功连接传输端点socket.makefile?我不确定在这种情况下的语法是什么。我最终没有使用connaddr就像我在服务器上使用更传统的方式一样,也许这就是我出错的地方?

- - 编辑 - -

Server.py我尝试使用connectionwithmakefile()函数时,如下所示:

.
.
.
    # accept the socket response from the client, get the connection object
    conn, addr = sock.accept()              # Note: execution waits here until the client calls sock.connect()
    print('socket accepted, got connection object')

    connFile = conn.makefile()

    while True:
        message = connFile.readline()
        print('received: ' + str(message))
    # end while
.
.
.

但这也不起作用,Client.py仍然像以前一样工作,但现在Server.py只是挂起:

$ python3 Server.py 
socket instantiated
socket binded
socket now listening
socket accepted, got connection object
(hangs here forever)

--- 编辑2 ---

现在我真的很困惑。基于这篇文章:

https://bugs.python.org/issue35928

我几乎复制了海报代码,所以 Server.py 现在看起来像这样:

# Server.py

import socket

# module-level variables
HOST='127.0.0.1'
PORT=65439

ACK_TEXT = 'text_received'

def main():
    with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:

        s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        s.bind((HOST, PORT))

        print(f'Waiting for connection on port {s.getsockname()[1]}')
        s.listen(1)

        conn, addr = s.accept()
        print(f'Connected by {addr}')

        with conn:
            f = conn.makefile(mode='rw')

            while True:
                print('before f.readline()')
                m = f.readline()
                print('after f.readline()')
                print(f'msg: {m!r}')

                if not m:
                    exit(0)

                f.write(m)
                f.flush()

# end main

if __name__ == '__main__':
    main()

并且Server.py仍然挂在阅读上!!

$ python3 Server.py 
Waiting for connection on port 65439
Connected by ('127.0.0.1', 47536)
before f.readline()

根据回复中的最后一篇文章,据说发帖人最初的担忧已经得到解决,因此现在应该可以使用了。我仍然不确定如何做到这一点。

--- 编辑3 ---

我正在使用Ubuntu 18.04.3最新的更新,Python 3.6.9如果这很重要

标签: pythonsockets

解决方案


在您的服务器代码中:

conn, addr = sock.accept()
calls sock.connect()
sockFile = sock.makefile()

    while True:
        message = sockFile.readline()

您制作了一个客户端套接字(conn),但您从未使用过它。客户端正在写入,因此您应该从客户端套接字(conn)读取另外我认为您应该从while循环内部调用accept。

while True:
        conn, addr = sock.accept()
        sockFile = conn.makefile()
        message = sockFile.readline()

推荐阅读