Or Azari
Or Azari

Reputation: 21

'socket.error: [Errno 9] Bad file descriptor' as I run my client

as I run my client, my server collapse,

it says:

Traceback (most recent call last):
      File "C:/Users/Or/PycharmProjects/2.6/cyber.py", line 17, in <module>
        data = client_socket.recv(1024)
      File "C:\Python27\lib\socket.py", line 174, in _dummy
        raise error(EBADF, 'Bad file descriptor')
    socket.error: [Errno 9] Bad file descriptor

server:

import socket
import random
import time

server_socket = socket.socket()
server_socket.bind(('0.0.0.0', 8820))
server_socket.listen(1)

(client_socket, client_address) = server_socket.accept()

TIME = time.asctime(time.localtime())
NAME = "Frank"
RAND = random.randrange(1,10)
EXIT = client_socket.close()
options = [TIME, NAME, RAND, EXIT]

data = client_socket.recv(1024)
if data == str(TIME):
    client_socket.send('Time is: ' + TIME)
elif data == str(NAME):
    client_socket.send('My name is: ' + NAME)
elif data == str(RAND):
    client_socket.send(RAND)
elif data == str(EXIT):
    EXIT




client_socket.close()
server_socket.close()

client:

import socket

my_socket = socket.socket()
my_socket.connect(('127.0.0.1', 8820))

theData = raw_input("enter command")
options = ['TIME', 'NAME', 'RAND', 'EXIT']
for z in options:
    if theData == z:
        my_socket.send(theData)
        data = my_socket.recv(1024)
        print data
    else:
        theData = raw_input("enter a real command")

what should I do?

Upvotes: 2

Views: 6152

Answers (1)

7stud
7stud

Reputation: 48599

The following line in your server blocks until your client connects:

(client_socket, client_address) = server_socket.accept()

After your client connects, your server does this:

  .... = client_socket.close()

Then your server does this:

 client_socket.recv(1024)

That ain't ever going to work.

what should I do?

Delete this line:

EXIT = client_socket.close()

Your code has several other problems:

1) You have no idea how much of the data that send() will actually send:

socket.send(bytes[, flags])
...
Applications are responsible for checking that all data has been sent; if only some of the data was transmitted, the application needs to attempt delivery of the remaining data. https://docs.python.org/3/library/socket.html#socket.socket.send

In other words, send() won't necessarily be able to send your entire message in one shot--hence the reason send() returns the number of bytes actually sent. You can use sendall() to ameliorate that problem.

2) However, with both send() and sendall() you have no idea whether your data was sent in 10 chunks, 5 chunks, or all in 1 chunk, so you have to use a loop in order to recv() the entire message:

data = []

while True:
    chunk = my_socket.recv()
    if not chunk: break  #When the other side closes the socket, chunk = ''
    data.append(chunk)

all_data = ''.join(data)

When the other side closes the socket, recv() will return a blank string.

3) Now the big one:

data = client_socket.recv(1024)

Your server has to use recv() in a loop to ensure that it reads the entire message from the client:

data = []

while True:
    chunk = client_socket.recv()
    if not chunk: break  #When the other side closes the socket, chunk = ''
    data.append(chunk)

all_data = ''.join(data)

But how is the read loop going to know when it has read all the data? Note that as written, the loop terminates when the other side closes the socket causing the recv() to return a blank string, which terminates the while loop. But, in your case the client doesn't close the socket after its send(), so the server's recv() will never return a blank string, and the while loop will continue trying to recv()--yet the client will have finished sending the message and will be waiting for a response. Deadlock.

Upvotes: 2

Related Questions