Reputation: 145
In an attempt to get a chat system working in Python using Windows, I have used the following code on the client-side:
import sys, socket, select
def chat_client():
if(len(sys.argv) < 3) :
print 'Usage : python chat_client.py hostname port'
sys.exit()
host = sys.argv[1]
port = int(sys.argv[2])
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. You can start sending messages'
sys.stdout.write('[Me] '); sys.stdout.flush()
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:
if sock == s:
# incoming message from remote server, s
data = sock.recv(4096)
if not data :
print '\nDisconnected from chat server'
sys.exit()
else :
#print data
sys.stdout.write(data)
sys.stdout.write('[Me] '); sys.stdout.flush()
else :
# user entered a message
msg = sys.stdin.readline()
s.send(msg)
sys.stdout.write('[Me] '); sys.stdout.flush()
if __name__ == "__main__":
sys.exit(chat_client())
However, I am getting the following error when attempting to connect to a server (which is running in Python too):
select.error: (10038, 'An operation was attempted on something that is not a socket')
This has something to do with sys.stdin.
I believe this is issue with file objects on Windows not being acceptable, but sockets are. On Windows, the underlying select function is provided by the WinSock library, and does not handle file descriptors that don’t originate from WinSock.
Is there a workaround to this to allow for a way to implement the chat_client.py code on Windows?
Upvotes: 1
Views: 3097
Reputation: 19375
Is there a workaround to this to allow for a way to implement the chat_client.py code on Windows?
You could manage with periodical checking of input activity, e. g. by replacing your select
statement with
# Get the list sockets which are readable, time-out after 1 s
read_sockets = select.select([s], [], [], 1)[0]
import msvcrt
if msvcrt.kbhit(): read_sockets.append(sys.stdin)
Note that in this example approach, when one began typing in a line, incoming messages will only be displayed after the input line is finished.
Upvotes: 1