【问题标题】:Client socket stops working after client closes program suddenly客户端突然关闭程序后客户端套接字停止工作
【发布时间】:2018-05-05 10:24:08
【问题描述】:

服务器代码开始监听。当我在客户端执行 F5 并等待时,代码运行得很好。如果我再次尝试 F5,在之前的连接尝试中,客户端程序无法建立连接(s == None),我需要解决这个问题,特别是因为每当我再次运行客户端时,它都会一直显示建立连接的同样问题。为了再次工作,我需要重新启动服务器程序。 在其他调试中,我知道它无法正常工作的方式,IDLE 打印“q”s 20 次,然后

无法打开套接字

无法读取结果。

我接受任何关于我的编码的建设性批评。编程对我来说只是一种爱好。这是我的两个代码:

服务器代码

import socket
import sys
import multiprocessing as mp
import time
import psycopg2 as psy

print("server is on!")
HOST = None
PORT = 50007

process = []

def checkin_room(room, passw, user, ip, port):
    print("main:checkin_room")
    conn = psy.connect("host=localhost dbname=pychat user=root password=codigo64")
    cr = conn.cursor()
    cr.execute("select * from rooms where name = '%s';")
    row = cr.fetchone()
    print("main: here")
    if row == None:
        cr.execute("insert into rooms (name,hashpw) values ('%s','%s');"%(room,passw))
        cr.execute("select id from rooms where name = '%s';"%(room))
        rid = cr.fetchone()[0]
        cr.execute("insert into users (rid,name,ip,port) values (%d,'%s','%s',%d);"%(rid,user,ip,port))
        print("new room")
        return 1 # room created
    else:
        cr.execute("select * from rooms where name = '%s' and hashpw = '%s';"%(room,passw))
        row = cr.fetchone()
        if row == None:
            print("wrong password for room")
            return 0 # wrong password
        else:
            cr.execute("select ip, port from users where rid = %d and ip != '%s';"%(row[0],ip))
            row = cr.fetchall()
            if row == None:
                print("no users in room")
                return []
            print("other users in room")
            return row # correct password: return ip and ports of users from room
    

def check_socket():
    print("Socket's being checked.")
    while True:
        s = None
        for res in socket.getaddrinfo(HOST, PORT, socket.AF_UNSPEC,
                                      socket.SOCK_STREAM, 0, socket.AI_PASSIVE):
            af, socktype, proto, canonname, sa = res
            try:
                s = socket.socket(af, socktype, proto)
            except OSError as msg:
                s = None
                continue
            try:
                s.bind(sa)
                s.listen(1)
            except OSError as msg:
                s.close()
                s = None
                continue
            break
##        if s is None:
##            print('could not open socket')
##            sys.exit(1)
        if s != None:
            conn, addr = s.accept()
            try:
                ip, port = addr
            except:
                print("problem: ",addr)
                s.close()
                s = None
                continue
            with conn:
                print('Connected by', addr)
                while True:
                    data = conn.recv(1024)
                    if not data:
                        break
                    cmd = eval(data.decode("utf-8"))
                    if cmd[0] == "checkin":
                        ret = checkin_room(cmd[1],cmd[2],cmd[3],ip,port)
                        conn.sendall(str(ret).encode("utf-8"))
            s.close()
                    

process.append(mp.Process(target = check_socket))
process[-1].start()
print("process started...")
time.sleep(1)
print("Command line ready for use.")
while True:
    cmd = input()
    if cmd == "end":
        for p in process:
            p.terminate()
        break
print("Program's over.")

客户端代码

import socket, sys

HOST = "123.123.123.123" # fake host
PORT = 50007

ROOM = "ufrj"
PASSW = "fundao"
USER = "coresh"

friends = []


def send_server(host, port, cmd):
    s = None
    print("client: here1")
    for i in range(20):
        for res in socket.getaddrinfo(host, port, socket.AF_UNSPEC, socket.SOCK_STREAM):
            af, socktype, proto, canonname, sa = res
            try:
                s = socket.socket(af, socktype, proto)
            except socket.error as msg:
                s = None
                continue
            try:
                s.connect(sa)
            except socket.error as msg:
                s.close()
                s = None
                continue
            break
        if s == None:
            print("qq")
        else:
            break
    if s is None:
        print ('could not open socket')
        return
    print("client: here2")
    s.sendall(bytearray(str(cmd).encode("utf-8")))
    print("here3")
    data = s.recv(1024)
    print("here4")
    s.close()
    print("closed")
    return eval(data.decode("utf-8"))


def checkin_room(room, passw, user):
    cmd = ["checkin", room, passw, user]
    ret = send_server(HOST, PORT, cmd)
    
    if ret == 1:
        print("Room's been created.")

    elif ret == 0:
        print("Wrong password.")

    elif type(ret) == list:
        if ret == []:
            print("Only you in the room.")
        else:
            friends += ret

    else:
        print("Can't read result.")
        
checkin_room(ROOM, PASSW, USER)

【问题讨论】:

    标签: python-sockets


    【解决方案1】:

    当你再次按 F5 时你正在做的是你正在切断程序而没有先关闭套接字。这会导致它挂起,您不能再次使用套接字。在重新启动程序之前让客户端到s.close()。这将完全关闭套接字并阻止套接字挂起。

    关于您的编码方式,请尝试在每行代码之间放置一个空行。这将帮助您阅读和调试代码。

    【讨论】:

      最近更新 更多