2013-05-13 33 views
7

我正在寫一個簡單的基於套接字的聊天程序,它允許服務器向客戶端發送和接收消息。客戶端可以發送消息給服務器,但是當我嘗試從服務器發送消息時,它會崩潰,說'文件'對象的屬性爲'recv'。基於套接字的簡單python聊天程序

Server.py

import socket 
import os 
import select 
import sys 

def prompt(): 
    sys.stdout.write('<You> ') 
    sys.stdout.flush() 

try: 
    server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 
except: 
    print 'Failed to create socket' 
    sys.exit() 

PORT = 9050 
HOST = '127.0.0.1' 
RECV_BUFFER = 4096 

server_socket.bind((HOST, PORT)) 
server_socket.listen(10) 

input = [server_socket, sys.stdin] 

print 'Chat Program' 
prompt() 

while 1: 

    inputready, outputready, exceptready = select.select(input,[],[]) 

    for sock in inputready: 

     if sock == server_socket: 
      client, address = server_socket.accept() 
      input.append(client) 
      #data = sock.recv(RECV_BUFFER) 
      #if data: 
       #sys.stdout.write(data) 
     else: 
      data = sock.recv(RECV_BUFFER) 
      if data: 
       sys.stdout.write(data) 
      else: 
       msg = sys.stdin.readline() 
       server_socket.send('\r<Server>: ' + msg) 
       prompt() 



server_socket.close() 

Client.py

import socket 
import os 
import select 
import sys 

def prompt(): 
    sys.stdout.write('<You> ') 
    sys.stdout.flush() 

HOST = '127.0.0.1' 
PORT = 9050 
try: 
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 
except socket.error: 
    print 'Failed to create socket' 
    sys.exit() 

s.connect((HOST, PORT)) 

print 'Connected to remote host. Start sending messages' 
prompt() 

while 1: 

    socket_list = [sys.stdin, s] 

    read_sockets, write_sockets, error_sockets = select.select(socket_list, [], []) 

    for sock in read_sockets: 
     if sock == s: 
      data = sock.recv(4096) 
      if not data: 
       print '\nDisconnected from chat server' 
       sys.exit() 
      else: 
       sys.stdout.write(data) 
       prompt() 
     else: 
      msg = sys.stdin.readline() 
      s.send('\r<Client>: ' + msg) 
      prompt() 
+0

這不是點對點,因爲它有一個服務器 – ioanD 2014-02-23 06:00:10

回答

4

那麼,在你的服務器,你正在做的(略)

input = [server_socket, sys.stdin] 
inputready, outputready, exceptready = select.select(input,[],[]) 
for sock in inputready: 
    if sock == server_socket: 
     ... 
    else: 
     data = sock.recv(RECV_BUFFER) 

所以,當出現一些這樣在sys.stdin,它不是server_socket所以它去else並試圖recv,但它不是一個插座。 stdin應該使用read而不是recv。像下面這樣的結構對我來說最有意義。

if sock == server_socket: 
    ... 
elif sock == sys.stdin: 
    data = sock.readline() 
    for s in input: 
     if s not in (server_socket, sys.stdin): 
      s.send(data) 
else: 
    ... 
+0

所以我應該有一個聲明,如果手中的東西從像keyobard: 如果襪子==標準輸入:味精= SYS .stdin.readline()server_socket.send()提示() – jtd92 2013-05-13 20:45:11

+0

當然,任何方式來保持'stdin'處理分開 – cmd 2013-05-13 20:47:53

+0

好吧現在我正在從server_socket.send('\ r :'+ msg)。我需要從服務器連接到客戶端嗎?謝謝 – jtd92 2013-05-13 20:55:26

0

我試圖從下面提供的鏈接相似類型的節目,但select()未在Windows操作系統支持的問題。

File objects on Windows are not acceptable, but sockets are. On 
Windows, the underlying select() function is provided by the WinSock 
library, and does not handle file descriptors that don’t originate 
from WinSock. 

http://www.binarytides.com/code-chat-application-server-client-sockets-python/