5

I wanted to make a server and a client with Python. It was supposed to make multiple connections, one, where the server is sending something to the client, and one where the client is sending something to the server.

The first connection worked fine, but the second one crashed with the message:

socket.error: [Errno 9] Bad file descriptor

Here is the Server:

import socket
import errno
import pickle

def Main():
    host = '188.174.233.99'
    port = 66666

    all_text = ['text1', 'text2', 'text3']

    all_description = ['Test \n Description1\n', 'Test \n Description1\n', 'Test \n Description1\n']

    all_images = ['unlock.png', 'unlock.png', 'unlock.png']
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM, socket.IPPROTO_TCP)
    s.bind((host, port))
    s.listen(1)


    while True:

        c, addr = s.accept()
        c.setblocking(0)

        print "Connection from: " + str(addr)


        command = c.recv(1024)

        if command == 'GIVEALL':
            textstring = pickle.dumps([all_text, all_images, all_description])#verwandelt Liste in String
            c.send(textstring)



        else:
            try:
                new_event = pickle.loads(command)
                print new_event
                caption = new_event[0]
                image = new_event[1]
                describtion = new_event[2]
                city = new_event[3]

            except:
                pass

        try:
            c.close()

            s.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
        except socket.error as e:
            if e.errno != errno.ECONNRESET:
                raise
            pass

if __name__ == '__main__':
    Main()

And here is the Client:

import socket import pickle

from kivy.properties import StringProperty
from kivy.properties import NumericProperty
from kivy.properties import ListProperty

class Netclient(object):

    def __init__(self):
        self.s = socket.socket()
        self.texte = []
        self.current = 'All'

        self.ip = '188.174.233.99'
        self.port = 66666

    def giveWid(self):
        print 'give Widgets executed'
        if self.current == 'All':
            self.texte, self.images, self.description = self.sentHOT(self.ip, self.port)

        return self.texte, self.images, self.description

    def sentHOT(self, host, port):

        self.s.connect((host, port))
        self.s.send('GIVEALL')#sends command

        recived_string = self.s.recv(1023)

        more_text = pickle.loads(recived_string)#verwandelt string in liste

        self.s.close()
        print 'closed'
        return more_text[0], more_text[1], more_text[2]


    def add_event(self, caption, image, description, city='Pawonkow'):
        new_event = [caption, image, description, city]
        new_compact_event = pickle.dumps(new_event)

        self.s.connect((self.ip, self.port))
        self.s.send(new_compact_event)

        self.s.close()


    n = Netclient()
    t, i, d = n.giveWid()
    print t
    n.add_event('new', 'new.png', 'ew event', 'Hanau')
Gilgamesch von Uruk
  • 351
  • 2
  • 5
  • 17
  • Server can't close connection ! Put every connection to in a thread, `close` method only acceptable on server side... – dsgdfg Jul 10 '16 at 14:51
  • You can use `close` method if want reject a client connection. – dsgdfg Jul 10 '16 at 14:52
  • Possible duplicate of [Getting Errno 9: Bad file descriptor in python socket](https://stackoverflow.com/questions/15958026/getting-errno-9-bad-file-descriptor-in-python-socket) – Evan Carroll Nov 08 '18 at 01:58

1 Answers1

5

The reason is that you are trying to reconnect a closed socket. You have to either create a new socket or reuse the old one as long as it's connected.

In method def sentHOT(...): comment the line self.s.close() and in method def add_event(...) comment the line self.s.connect((self.ip, self.port)) then should work. Further, please take a look at this tutorial, it helps you with socket programming.

mitghi
  • 889
  • 7
  • 20
  • 2
    Good catch. I did not understand the problem first. I thought he means that he was starting 2 clients at the same time. I have deleted my post as it was not the right answer. – jobou Jul 10 '16 at 13:31
  • what would it look like, if I had a new socket for both functions? – Gilgamesch von Uruk Jul 11 '16 at 10:48
  • @GilgameschvonUruk Can you explain a bit more ? Do you mean creating a new socket each time the function is called ? – mitghi Jul 12 '16 at 09:03
  • yes, I actually did it, and it worked ,kind of, shoud I post the code? – Gilgamesch von Uruk Jul 13 '16 at 07:11
  • Sure if you like to. It will be helpful as well if you take a look to various networking architectures ( threading, native multiplexing APIs ( epoll, select, ... ) ). @jobou have good references for this topic. – mitghi Jul 13 '16 at 08:09
  • 1
    Look here : http://stackoverflow.com/a/10810769/1951430 you have base native python classes to do this. Note the comment at the end with the Forking or Threading mixin, it is important because natively the TCPServer behaves synchronously (it waits for the end of one request to process the next) – jobou Jul 13 '16 at 09:21