基本的python套接字服务器应用程序不会产生预期的输出

时间:2014-04-26 02:05:08

标签: python sockets

我试图在python中编写一个基本的服务器/客户端应用程序,客户端将数字1-15发送到服务器,服务器将其打印在服务器端控制台上。

客户代码:

import socket
clientsocket.connect(('localhost', 8303))
def updateX():
    x = 0
    while (x < 15):
        x
        clientsocket.send(format(x))
        print x
        x = x+1

updateX()

服务器:

import socket

HOST = 'localhost'
PORT = 8303
s= socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((HOST, PORT))
s.listen(5) # become a server socket, maximum 5 connections
connection, address = s.accept()

while True:
    connection, address = s.accept()
    buf = connection.recv(64)
    print buf

在服务器运行时运行客户端的输出导致无输出,仅打印1或仅打印12.想法?

2 个答案:

答案 0 :(得分:2)

在进入服务器端的主循环之前,您接受连接:

connection, address = s.accept()

但是在循环中你首先接受一个连接:

while True:
    connection, address = s.accept()
    buf = connection.recv(64)
    print buf

因此,您永远不会从第一个连接中读取。这就是你没有看到任何输出的原因。

另请注意,在每次迭代时接受新连接都是错误的(对于您正在尝试做的事情)。即使您继续建立新的客户端连接,服务器也会在每次迭代时接受连接并从套接字读取一次,但随后继续下一次迭代并等待新连接,从不读取客户端发送的更多数据。您应该在同一个连接对象上进行多次recv调用。

您可能会发现this tutorial有帮助。

答案 1 :(得分:1)

有多个错误:

  • socket.send()可能只发送部分内容,而是使用socket.sendall()代替
  • format(12)返回'12'因此,即使您的代码发送了所有号码并且服务器正确接收了它们,它也会看到'01234567891011121314',即个别号码未分开
  • double socket.accept()mentioned by @Alp导致忽略第一个连接
  • socket.recv(64)可能返回少于64个字节,你需要一个循环,直到它返回一个空字节串(意思是EOF)或者使用socket.makefile()

客户端:

#!/usr/bin/env python
"""Send numbers in the range 0..14 inclusive as bytes e.g., 10 -> b'\n'

Usage: python client.py [port]
"""
import sys
import socket
from contextlib import closing

port = 8686 if len(sys.argv) < 2 else int(sys.argv[1])
with closing(socket.create_connection(('localhost', port))) as sock:
    sock.sendall(bytearray(range(15))) # send each number as a byte
    sock.shutdown(socket.SHUT_RDWR)    # no more sends/receives

您需要知道数据中数字的分离方式。在这种情况下,使用固定格式:每个数字是一个单独的字节。它仅限于小于256的数字。

和相应的服务器:

#!/usr/bin/env python
"""
Usage: python server.py [port]
"""
from __future__ import print_function
import sys
import socket
from contextlib import closing

host = 'localhost'
port = 8686 if len(sys.argv) < 2 else int(sys.argv[1])

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # ipv4 version
try:
    s.bind((host, port))
    s.listen(5)
    print("listening TCP on {host} port {port}".format(**vars()))
    while True:
        conn, addr = s.accept()
        with closing(conn), closing(conn.makefile('rb')) as file:
            for byte in iter(lambda: file.read(1), b''):
                # print numerical value of the byte as a decimal number
                print(ord(byte), end=' ')
            print("") # received all input from the client, print a newline
except KeyboardInterrupt:
    print('Keyboard interrupt received, exiting.')
finally:
    s.close()