无法使用python

时间:2016-03-29 18:32:02

标签: python sockets server client chat

我有一个服务器和一个客户端,他们可以相互连接,我可以从客户端发送到服务器,但反之亦然。当我试图将数据发送回客户端时,程序失败。

client.py

from tkinter import *
import socket
import threading

tLock = threading.Lock()
shutdown = False

host = '::1';
port = 5000;

s = socket.socket(socket.AF_INET6, socket.SOCK_STREAM)

class Application(Frame):
def __init__(self, master=None):
    #Create master frame
    Frame.__init__(self,master)
    self.grid()
    self.master.title("Test 1")
    self.conn=False #State of connection to server

    #Configure main frame
    for r in range (4):
        self.master.rowconfigure(r, weight=1)
    for c in range (2):
        self.master.columnconfigure(c)

    #Create sub frames
    TopFrame=Frame(master)
    TopFrame.grid(row=0, column=0, rowspan=3)
    BottomFrame=Frame(master, bg="green")
    BottomFrame.grid(row=4, column=0, rowspan=3)
    SideFrame=Frame(master, bg="red")
    SideFrame.grid(column=1, row=0, rowspan=4)

    #Create Chat log
    self.chatlog=Text(TopFrame)
    self.chatlog.pack(padx=5, pady=5)


    #messenger and send button
    self.e1=Entry(BottomFrame, width=92)
    self.e1.pack(side=LEFT, pady=5, padx=5)
    sendButton=Button(BottomFrame, text="Send", command=self.sendmessage, height = 1, width = 10)
    sendButton.pack(side=LEFT)

    #Create connect disconnect buttons
    b1=Button(SideFrame, text="Connect", command=self.connect)
    b1.grid(row=0, column=0, padx=5, pady=5)
    b2=Button(SideFrame, text="Disconnect", command=self.disconnect)
    b2.grid(row=1, column=0, padx=5, pady=5)


def connect(self): #Connect to server
    self.chatlog['state'] = NORMAL
    self.chatlog.insert(END, ("===ATTEMPTING TO CONNECT TO SERVER\n"))
    self.chatlog['state'] = DISABLED
    self.chatlog.yview(END)

    s.connect((host,port))
    self.chatlog['state'] = NORMAL
    self.chatlog.insert(END, (s))
    self.chatlog['state'] = DISABLED
    self.chatlog.yview(END)

    self.chatlog['state'] = NORMAL
    self.chatlog.insert(END, ("\n\n PLEASE ENTER A USER NAME AND SEND"))
    self.chatlog['state'] = DISABLED
    self.chatlog.yview(END)
    self.conn=True
    print("Connected") #Connection successful

    # M- Adding threading for receiving messages
    rT = threading.Thread(target=self.receving, args=("RecvThread",s))
    rT.start()


    # When attempting to connect a second time, produces OS error: an operation was attempted on something that is not a socket

def disconnect(self):
    if self.conn: #Tests to see if client is connected
        s.close()
        self.chatlog['state'] = NORMAL
        self.chatlog.insert(END, ("===DISCONNECTED FROM SERVER.\n"))
        self.chatlog['state'] = DISABLED
        self.chatlog.yview(END)
        self.conn=False
    else: #Prevents attempting to disconnect when already disconnected
        self.chatlog['state'] = NORMAL
        self.chatlog.insert(END, ("===YOU AREN'T CURRENTLY CONNECTED.\n"))
        self.chatlog['state'] = DISABLED
        self.chatlog.yview(END)


def sendmessage(self):
    if self.conn: #Prevents sending if not connected
        self.msg=self.e1.get()
        if self.msg == "": #Empty message catcher
            self.chatlog['state'] = NORMAL
            self.chatlog.insert(END, ("===YOU CANNOT SEND AN EMPTY MESSAGE.\n" ))
            self.chatlog['state'] = DISABLED
            self.chatlog.yview(END)
        else:
            self.send_data(self.msg) #Sends message to the server
            self.e1.delete(0, END)
    else:
            self.chatlog['state'] = NORMAL
            self.chatlog.insert(END, ("===YOU ARE NOT CONNECTED TO A SERVER. YOU CANNOT SEND A MESSAGE.\n" ))
            self.chatlog['state'] = DISABLED
            self.chatlog.yview(END)

# M- Method to handle receiving from the server
# adds the data to the chat log.
def receving(self, name, sock):
    while not shutdown:
        try:
            tLock.acquire()
            while True:
                data, addr = sock.recvfrom(1024)
                self.chatlog['state'] = NORMAL
                self.chatlog.insert(END, (data + '\n'))
                self.chatlog['state'] = DISABLED
                self.chatlog.yview(END)
        except:
            pass
        finally:
            tLock.release()

def send_data(self, message):
    try:
        s.send(message.encode('UTF-8'))
    except:
            self.chatlog['state'] = NORMAL
            self.chatlog.insert(END, ("===THE PREVIOUS MESSAGE DIDN'T SEND. THIS IS POSSIBLY DUE TO A SERVER ERROR.\n"))
            self.chatlog['state'] = DISABLED
            self.chatlog.yview(END)


root = Tk()
app = Application(root)
app.mainloop()

Server.py

import socket
import threading
import sys

hosts=["::1"]
port=5000

#dictionay to hold the socket as the key and the user name as the value
dic = {}

class Server:
def __init__ (self,hosts,port):
    self.host=hosts
    self.port=port
    self.socketserver=socket.socket(socket.AF_INET6, socket.SOCK_STREAM)
    self.socketserver.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    print("Socket has been created successfully")
    for i in hosts:
        try:
            host=i
            self.socketserver.bind((host,port))
            print("Connection succeded to address",i)
            print ("The server is now binded to the following IP address",host,"Port",port)
            break
        except socket.error:
            print("Connection failed to address",i)
        else: 
            sys.exit()

def Accept_connections(self):
    while True:
        self.socketserver.listen(10)
        print("Socket is now awaiting connections")
        server, clientaddress = self.socketserver.accept()
        print("Connection enstablished with: " +str(clientaddress))   
        threading.Thread(target = self.message,args = (server,clientaddress),).start()

def message(self,server,clientaddress):
    while True:
        try:
            data= server.recv(1024)
            print("data ", data)
            #check to see if it is a new socket that is not in the stored
            #socket dictionary
            if server not in dic.keys():
                print("if statement")
                #if it is a new socket
                #add the socket and the user name
                dic[server] = data
                for key in dic:
                    #send the joined message to the users
                    print("failing")
                    key.send("\n\n" + data + " has joined the chat")
            else:
                #alias is a variable used to store the sockets username
                alias = dic[server]
                for key in dic:
                    #send the message to the sockets in the dictionary
                    key.send(alias + ": " +data)

        except:
            server.close()
            #edit this bit !
            print("Data transfer failed")
            return False

Server(hosts,port).Accept_connections()

该计划失败于:

    key.send("\n\n" + data + " has joined the chat")

当客户端连接时,输入一个名为的用户名。这将它与字典中的套接字一起存储。循环遍历套接字以通知其已加入的其他客户端时发生错误。任何帮助都会很棒。这是在python27上工作,但是当我更新到python34时已经停止了。

1 个答案:

答案 0 :(得分:1)

管理以找到修复程序。当我升级到3时,发送停止工作,因为它试图发送字符串。 Python 3需要发送字节。

key.send(data + b' joined')

是解决方案