python3 - broken pipe error when using socket.send()
Question: I am programming a client-server instant message program. I created a similar
program in Python 2, and am trying to program it in Python 3. The problem is
when the server takes the message and tries to send it to the other client, it
gives me "[Errno 32] Broken Pipe" and exits.

I have done some research, and found that this occurs when the client
disconnects, so I did some more testing but could not find when the client
disconnects. (I am using Ubuntu 14.04 and Python 3.4)

Here is the server code:

    
    
    import socket, select, sys
    
    def broadcast(sock, messaged):
        for socket in connection_list:
            if socket != s and socket != sock:
            # Here is where it gives me the broken pipe error
                try:
                    s.send(messaged.encode("utf-8"))
                except BrokenPipeError as e:
                    print(e)
                    sys.exit()
    connection_list = []
    host = ''
    port = 5558
    
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    s.bind((host,port))
    s.listen(5)
    
    connection_list.append(s)
    read_sockets,write_sockets,error_sockets = select.select(connection_list,[],[])
    while True:
        for sock in read_sockets:
            if sock == s:
                conn, addr = s.accept()
                connection_list.append(conn)
                client = "Client (%s,%s) connected" % addr
                print(client)
                broadcast(sock,client)
    
            else:
                try:
                    data = sock.recv(2048)
                    decodeddata = data.decode("utf-8")
                    if data:
                        broadcast(sock, decodeddata)
                except:
                    offline = "Client " + addr + "is offline"
                    broadcast(sock, offline)
                    print(offline)
                    connection_list.remove(sock)
                    sock.close()
                    continue
    

And the client code:

    
    
    import socket, select, string, sys, time
    
    def prompt(data) :
         print("<You> " + data)
    def Person(data) :
        print("<Receiver> " + data)
    
    if __name__ == "__main__":
    
        host = "localhost"
        port = 5558
    
        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        s.settimeout(2)
    
        try:
            s.connect((host,port))
        except:
            print('Unable to connect')
            sys.exit()
        print('Connected.')
        socket_list = [s]
        read_sockets,write_sockets,error_sockets = select.select(socket_list,[],[])
        while 1:
            for sock in read_sockets:
                if sock == s:
                    try:
                        time.sleep(1)
                        data = sock.recv(1024)             
                        Person(data.decode("utf-8"))
                    except:
                        msg = input("Send a message: ")
                        try:
                            s.send(str.encode(msg))
                        except:
                            print("Server is offline")
                            sys.exit()
    
    
                else:
                    print("Server is offline")
                    sys.exit()
    


Answer: There are two problems that you have to fix to make this work.

First, on both the client side and the server side, you have to put the
`select` _inside_ the loop, not outside. Otherwise, if there was something to
read before you got to the loop, you'll recv over and over, and if there
wasn't, you'll never recv. Once you fix this, you can get rid of the
`time.sleep(1)`. (You should _never_ need a `sleep` to solve a problem like
this; at best it masks the problem, and usually introduces new ones.)

Meanwhile, on the server side, inside `broadcast`, you're doing `s.send`. But
`s` is your listener socket, not a connected client socket. You want
`socket.send` here, because `socket` is each socket in `connection_list`.

* * *

There are a number of unrelated problems in your code as well. For example:

  * I'm not sure what the `except:` in the client is _supposed_ to be catching. What it mainly seems to catch is that, about 50% of the time, hitting ^C to end the program triggers the send prompt. But of course, like any bare `except:`, it also masks any other problems with your code.
  * There's no way to send any data back and forth other than the "connected" message except for that `except:` clause.
  * `addr` is a tuple of host and port, so when someone goes offline, the server raises a `TypeError` from trying to format the offline message.
  * `addr` is always the last client who connected, not the one who's disconnecting.
  * You're not setting your sockets to nonblocking mode.
  * You're not checking for EOF on the `recv`. This means that you don't actually detect that a client has gone offline until you get an error. Which normally happens only after you try to `send` them a message (e.g., because someone else has connected or disconnected).

