2014-01-09 128 views
0

我正在學習使用python進行套接字編程。我的第一項任務是寫一個client.py和一個server.py。 client發送消息給serverserver每次收到16 bytes的消息。收到完整消息後,它會將相同的消息發送回client。 所以它很簡單。服務器的積壓爲1.服務器將消息發送給客戶端後,應關閉客戶端連接並打開服務器以接收新連接。 我當前的代碼在最後一步失敗。它無法接收新的連接。這是拋出錯誤。我甚至找出了錯誤。但我不知道如何解決這個問題。嘗試連接到服務器時出現錯誤,下一次使用python中的套接字連接

錯誤來自server.py,因爲我打電話給sock.accept(),但我已經關閉了sock。 讓我解釋一下我的server.py代碼:我有兩個while loopsouter loop尋找新的連接,並且inner loop查看來自連接的處理請求,即它只是簡單地接收數據,等待接收到所有數據並將其發送回客戶端並最終關閉連接。

我被要求不要改變兩個while loops的結構,但只是實現它們。 任何對此的想法或意見:

client.py

import socket 
import sys 


def client(msg, log_buffer=sys.stderr): 
    server_address = ('localhost', 10000) 
    sock=socket.socket(socket.AF_INET,socket.SOCK_STREAM,socket.IPPROTO_IP) 
    sock.connect(server_address) 
    print >>log_buffer, 'connecting to {0} port {1}'.format(*server_address) 
    try: 
     print >>log_buffer, 'sending "{0}"'.format(msg) 
     sock.sendall(msg) 
     chunk = '' 
     done=False; 
     while not done: 
      chunk+=sock.recv(16) 
      if chunk==msg: 
       done=True 

     print >>log_buffer, 'received "{0}"'.format(chunk) 
    finally: 
     print >>log_buffer, 'closing socket' 
     sock.close() 


if __name__ == '__main__': 
    if len(sys.argv) != 2: 
     usg = '\nusage: python echo_client.py "this is my message"\n' 
     print >>sys.stderr, usg 
     sys.exit(1) 

    msg = sys.argv[1] 
    client(msg) 

Server.py

import socket 
import sys 


def server(log_buffer=sys.stderr): 
    # set an address for our server 
    address = ('127.0.0.1', 10000) 
    sock=socket.socket(socket.AF_INET,socket.SOCK_STREAM,socket.IPPROTO_IP) 
    sock.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1) 


    # log that we are building a server 
    print >>log_buffer, "making a server on {0}:{1}".format(*address) 

    sock.bind(address) 
    sock.listen(1) 

    try: 
     # the outer loop controls the creation of new connection sockets. The 
     # server will handle each incoming connection one at a time. 
     while True: 
      print >>log_buffer, 'waiting for a connection' 

      conn,add=sock.accept() 
      addr=(conn,add) 
      try: 
       print >>log_buffer, 'connection - {0}:{1}'.format(*addr) 

       # the inner loop will receive messages sent by the client in 
       # buffers. When a complete message has been received, the 
       # loop will exit 
       data = '' 
       while True: 

        recvdata=conn.recv(16) 
        print recvdata 
        data+=recvdata 
        print >>log_buffer, 'received "{0}"'.format(data) 
        print >>log_buffer, "len of received data: {0}".format(len(recvdata)) 
        if len(recvdata)<16: 
         print >>log_buffer,"sending data" 
         conn.sendall(data) 
         break 
       conn.close() 


      finally: 

       sock.close() 


    except KeyboardInterrupt: 

     sock.close() 


if __name__ == '__main__': 
    server() 
    sys.exit(0) 

我跑python server.py in one terminal and蟒蛇client.py 「這是第一條消息把我送回去。」`不同終奌站。客戶端連接按預期正常丟失。但我在服務器端(接近尾端)出現以下錯誤:

making a server on 127.0.0.1:10000 
waiting for a connection 
connection - <socket._socketobject object at 0x100849c20>:('127.0.0.1', 50626) 
sairam hopefully 
received "sairam hopefully" 
len of received data: 16 
this works lets 
received "sairam hopefully this works lets" 
len of received data: 16 
c 
received "sairam hopefully this works lets c" 
len of received data: 2 
sending data 
waiting for a connection 
Traceback (most recent call last): 
    File "echo_server.py", line 89, in <module> 
    server() 
    File "echo_server.py", line 39, in server 
    conn,add=sock.accept() 
    File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/socket.py", line 202, in accept 
    sock, addr = self._sock.accept() 
    File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/socket.py", line 170, in _dummy 
    raise error(EBADF, 'Bad file descriptor') 
socket.error: [Errno 9] Bad file descriptor 

回答

0

您正在關閉sock在您的while循環中。不要這樣做。 sock是您持久的服務器套接字,需要保持打開狀態以偵聽新連接。 conn是您的臨時套接字,它只需要保持打開一個連接的長度。

關閉conn每次連接後關閉sock當服務器需要終止時。

更簡單地說,更換這些線路:

 finally: 
      sock.close() 

 finally: 
      conn.close() 
+0

是的,我是這麼認爲的。但是對於我的指令說'#TODO:當內部循環退出時,這個'finally'子句將會被擊中。當客戶端連接時,利用這個機會關閉上面創建的套接字 。將 #呼叫替換爲下面的'pass',這只是爲了防止 #語法問題' –

+0

在這種情況下,用'conn.close()'替換'sock.close()'。他們的關鍵在於指令:「*關閉您在上面創建的套接字**當客戶端連接***」。在你的情況下,這是'conn',而不是'sock'。 –

+0

固定,但我現在得到'socket.error:[Errno 48]地址已經在使用中'雖然我'sock.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)'重新使用地址? –

0

你所要做的是一個簡單的echo服務器,我相信你可以實現更加簡單。

服務器:

import socket 

host = '' 
port = 50000 
backlog = 5 
size = 1024 
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 
s.bind((host,port)) 
s.listen(backlog) 
while 1: 
    client, address = s.accept() 
    data = client.recv(size) 
    if data: 
     client.send(data) 
    client.close() 

客戶:

import socket 

host = 'localhost' 
port = 50000 
size = 1024 
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 
s.connect((host,port)) 
s.send('Hello, world') 
data = s.recv(size) 
s.close() 
print 'Received:', data 
相關問題