Zach Tusing Zach Tusing - 3 months ago 84
Python Question

TCP Chat server Python 3.4

There is an error in my client side code. The error is,"The operation was attempted on something that is not a socket." how do I go about fixing this error. I also know that my input is not sent to the server yet, If you guys have any tips on how I accomplish that I would also love them. Thanks! The code showed below:

import socket, select, string, sys


def prompt() :
sys.stdout.write('<You> ')
sys.stdout.flush()

#main function
if __name__ == "__main__":

host = "localhost"
port = 5000

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.settimeout(2)

# connect to remote host
try :
s.connect((host, port))
except :
print('Unable to connect')
sys.exit()

print('Connected to remote host. Start sending messages')
prompt()
input = input()

while 1:
socket_list = [sys.stdin, s]

# Get the list sockets which are readable
read_sockets, write_sockets, error_sockets = select.select(socket_list , [], [])

for sock in read_sockets:
#incoming message from remote server
if sock == s:
data = sock.recv(4096)
if not data :
print('\nDisconnected from chat server')
sys.exit()
else :
#print data
sys.stdout.write(data)
prompt()

#user entered a message
else :
msg = sys.stdin.readline()
s.send(msg)
prompt()


Server Code:

import socket, select

#Function to broadcast chat messages to all connected clients
def broadcast_data (sock, message):
#Do not send the message to master socket and the client who has send us the message
for socket in CONNECTION_LIST:
if socket != server_socket and socket != sock :
try :
socket.send(message)
except :
# broken socket connection may be, chat client pressed ctrl+c for example
socket.close()
CONNECTION_LIST.remove(socket)

if __name__ == "__main__":

# List to keep track of socket descriptors
CONNECTION_LIST = []
RECV_BUFFER = 4096 # Advisable to keep it as an exponent of 2
PORT = 5000

server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# this has no effect, why ?
server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
server_socket.bind(("0.0.0.0", PORT))
server_socket.listen(10)

# Add server socket to the list of readable connections
CONNECTION_LIST.append(server_socket)

print("Chat server started on port " + str(PORT))

while 1:
# Get the list sockets which are ready to be read through select
read_sockets,write_sockets,error_sockets = select.select(CONNECTION_LIST,[],[])

for sock in read_sockets:
#New connection
if sock == server_socket:
# Handle the case in which there is a new connection recieved through server_socket
sockfd, addr = server_socket.accept()
CONNECTION_LIST.append(sockfd)
print("Client (%s, %s) connected" % addr)

broadcast_data(sockfd, "[%s:%s] entered room\n" % addr)

#Some incoming message from a client
else:
# Data recieved from client, process it
try:
#In Windows, sometimes when a TCP program closes abruptly,
# a "Connection reset by peer" exception will be thrown
data = sock.recv(RECV_BUFFER)
if data:
broadcast_data(sock, "\r" + '<' + str(sock.getpeername()) + '> ' + data)

except:
broadcast_data(sock, "Client (%s, %s) is offline" % addr)
print("Client (%s, %s) is offline" % addr)
sock.close()
CONNECTION_LIST.remove(sock)
continue

server_socket.close()

Answer

On Microsoft Windows, python's socket library is implemented using Winsock. Winsock isn't integrated into the operating system like the sockets library on unixy systems. It has its own idea of what a socket is, and does not recognize system pipes or consoles.

On Windows you get the error you see

>>> import platform
>>> print platform.system()
Windows
>>> import socket
>>> import select
>>> import sys
>>> select.select([sys.stdin],[],[])
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
select.error: (10038, 'An operation was attempted on something that is not a socket')
>>> select.select([sys.stdin.fileno()],[],[])
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
select.error: (10038, 'An operation was attempted on something that is not a socket')
>>>

On linux it works

>>> import platform                                                                                                                         
>>> print platform.system()
Linux                                                                                                                                       
>>> import socket
>>> import select
>>> import sys
>>> select.select([sys.stdin],[],[],0)
([], [], [])
>>>