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()
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)
([], [], [])
>>>
I couldn't see anything wrong so I ran your code on my linux box with python3.4 and got no errors from either server or the client and they connected without issue. The only thing I can think of is with your version of python or OS like tdelaney suggested. I don't have a windows box to test with so I can't confirm if it's OS specific.
Use input = [s] #instead of socket_list = [sys.stdin, s]
Related
I'm struggling with getting reply back to client when pinging through socket server.
Trying to create something simple, where I can ping servers from client through socket server.
Client checks that socket server is online, socket server in "server" will respond status. Client sends the ping command to socket server, socket server initiate the ping to where ever. Raw printout will be sent to client.
What's the best way to do it?
First time working with sockets.
Server
#!/usr/bin/python3
import socket
import sys
HOST = '127.0.0.1'
PORT = 8085
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
print('Socket created')
# Bind socket
try:
s.bind((HOST, PORT))
except socket.error as msg:
print('Bind failed. Error Code : ' + str(msg[0]) + ' Message ' + msg[1])
sys.exit()
print('Socket bind complete')
#Start listening on socket
s.listen(10)
print('Socket now listening')
# Talk with client
while 1:
#wait to accept a connection - blocking call
conn, addr = s.accept()
print('Connected')
while True:
dataFromClient = conn.recv(1024)
print(dataFromClient.decode('utf-8'))
if not dataFromClient:
print("[Client] Disconnected")
break
conn.sendall(dataFromClient)
s.close()
Client
#!/usr/bin/python3
import socket
import subprocess
import os
SERVER = "127.0.0.1"
clientSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
clientSocket.connect((SERVER,8085))
os.system("clear")
os.system("cls")
while True:
data = input("Input: ")
clientSocket.send(data.encode())
# dataFromServer = clientSocket.recv(1024)
# print(dataFromServer.decode())
if data == "ping":
input1 = str(input("Enter command: "))
with subprocess.Popen(input1,shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) as proc:
for line in proc.stdout:
clientSocket.send(line)
print(proc.communicate())
elif data == "help":
print("Command: pingdl,destip=<isp>,repeat=<amount>")
clientSocket.close()
I am trying to implement the code as written here:
https://www.geeksforgeeks.org/simple-chat-room-using-python/
I can get it to run properly but cannot find a way to close the connection. The code simply runs until I enter a keyboard interrupt. I'l like to implement a keyword that will shut down the client and server and free the port.
I've implemented the client code to exit if the message is "quit" but the same technique isn't working in the server code. I keep getting caught on the "conn, addr = server.accept()" line and it returns the error
Traceback (most recent call last):
File "newServer.py", line 66, in <module>
conn, addr = server.accept()
File "/Users/######/anaconda3/lib/python3.7/socket.py", line 212, in accept
fd, addr = self._accept()
ConnectionAbortedError: [Errno 53] Software caused connection abort
Any help would be appreciated!
Edit: Adding code
server.py:
import socket
import select
from _thread import *
import threading
import sys
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
"""
the first argument AF_INET is the address domain of the socket. This is used when we have an Internet Domain
with any two hosts
The second argument is the type of socket. SOCK_STREAM means that data or characters are read in a continuous flow
"""
server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
IP_address = "127.0.0.1"
Port = 12230
server.bind((IP_address, Port))
#binds the server to an entered IP address and at the specified port number. The client must be aware of these parameters
server.listen(100)
#listens for 100 active connections. This number can be increased as per convenience
list_of_clients=[]
def clientthread(conn, addr):
conn.send("Welcome to this chatroom!".encode())
#sends a message to the client whose user object is conn
while True:
try:
message = conn.recv(2048).decode()
if message:
print ("<" + addr[0] + "> " + message)
message_to_send = "<" + addr[0] + "> " + message
broadcast(message_to_send,conn)
#prints the message and address of the user who just sent the message on the server terminal
else:
remove(conn)
except:
continue
def broadcast(message,connection):
for clients in list_of_clients:
if clients!=connection:
try:
clients.send(message.encode())
except:
clients.close()
remove(clients)
def remove(connection):
if connection in list_of_clients:
list_of_clients.remove(connection)
while True:
conn, addr = server.accept()
"""
Accepts a connection request and stores two parameters, conn which is a socket object for that user, and addr which contains
the IP address of the client that just connected
"""
list_of_clients.append(conn)
print (addr[0] + " connected")
#maintains a list of clients for ease of broadcasting a message to all available people in the chatroom
#Prints the address of the person who just connected
start_new_thread(clientthread,(conn,addr))
#creates and individual thread for every user that connects
conn.close()
server.close()
client.py
import socket
import select
import sys
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
IP_address = "127.0.0.1"
Port = 12230
server.connect((IP_address, Port))
while True:
# maintains a list of possible input streams
sockets_list = [sys.stdin, server]
""" There are two possible input situations. Either the
user wants to give manual input to send to other people,
or the server is sending a message to be printed on the
screen. Select returns from sockets_list, the stream that
is reader for input. So for example, if the server wants
to send a message, then the if condition will hold true
below.If the user wants to send a message, the else
condition will evaluate as true"""
read_sockets,write_socket, error_socket = select.select(sockets_list,[],[])
for socks in read_sockets:
if socks == server:
message = socks.recv(2048).decode()
print (message)
else:
message = input("Message: ")
server.send(message.encode())
print("<You>")
print(message)
server.close()
I am trying to establish a connection to a server, and send some data to it..
The problem is that, if i try to debug the connection using this MICHAEL SIEGENTHALER | TCP/UDP Debugging Tools
which clearly shows that there is no issue with the communication, and even some form of random input will result in a data coming out.
but when i try to code it in python, using the same settings, are no response received.. It stalls after it has sent the message, i am not sure whether whether it has send the message, or skipped it?
It seems like my server aren't receiving the message i sent to it, and therefore don't reply.. but what is different?
import socket #for sockets
import sys #for exit
# create dgram udp socket
try:
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
except socket.error:
print ('Failed to create socket')
sys.exit()
host = 'localhost';
port = 5634;
while(1) :
try :
#Set the whole string
s.sendto(("-1-117230").encode('utf-8'),('10.2.140.183', 9008))
print("sent")
# receive data from client (data, addr)
d = s.recvfrom(1024)
reply = d[0]
addr = d[1]
print ('Server reply : ' + reply)
except socket.error as msg:
print ('Error Code : ' + str(msg[0]) + ' Message ' + msg[1])
sys.exit()
what is different from the code, and the way the debugging tool test it?
I tried to code it in c++ using boost, but as i had the same issue, i went on to trying in python to see whether that would make a bit more sense.
---Updated --
import socket #for sockets
import sys #for exit
# create dgram udp socket
try:
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
server_adress = ('10.2.140.183',5634)
s.bind(server_adress)
except socket.error:
print ('Failed to create socket')
sys.exit()
while(1) :
try :
#Set the whole string
s.sendto(("-1-117230").encode('utf-8'),('10.2.140.183', 9008))
print("sent")
# receive data from client (data, addr)
d = s.recvfrom(1024)
reply = d[0]
addr = d[1]
print ('Server reply : ' + reply)
except socket.error as msg:
print ('Error Code : ' + str(msg[0]) + ' Message ' + msg[1])
sys.exit()
You are missing the binding method.
This is kind of an echo server:
import socket
import sys
host = ''
port = 8888
buffersize = 1
server_address = (host, port)
socket_UDP = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
socket_UDP.bind(server_address)
while True:
data, from_address = socket_UDP.recvfrom(buffersize)
if data:
socket_UDP.sendto(bytes("b"*buffersize, "utf-8"), from_address)
socket_UDP.close()
Here is my server code.
# chat_server.py
import sys, socket, select
HOST = ''
SOCKET_LIST = []
RECV_BUFFER = 4096
PORT = 9009
def chat_server():
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
server_socket.bind((HOST, PORT))
server_socket.listen(10)
# add server socket object to the list of readable connections
SOCKET_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
# 4th arg, time_out = 0 : poll and never block
ready_to_read,ready_to_write,in_error = select.select(SOCKET_LIST,[],[],0)
for sock in ready_to_read:
# a new connection request recieved
if sock == server_socket:
sockfd, addr = server_socket.accept()
SOCKET_LIST.append(sockfd)
print "Client (%s, %s) connected" % addr
broadcast(server_socket, sockfd, "[%s:%s] entered our chatting room\n" % addr)
# a message from a client, not a new connection
else:
# process data recieved from client,
try:
# receiving data from the socket.
data = sock.recv(RECV_BUFFER)
if data:
# there is something in the socket
broadcast(server_socket, sock, "\r" + '[' + str(sock.getpeername()) + '] ' + data)
else:
# remove the socket that's broken
if sock in SOCKET_LIST:
SOCKET_LIST.remove(sock)
# at this stage, no data means probably the connection has been broken
broadcast(server_socket, sock, "Client (%s, %s) is offline\n" % addr)
# exception
except:
broadcast(server_socket, sock, "Client (%s, %s) is offline\n" % addr)
continue
server_socket.close()
# broadcast chat messages to all connected clients
def broadcast (server_socket, sock, message):
for socket in SOCKET_LIST:
# send the message only to peer
if socket != server_socket and socket != sock :
try :
socket.send(message)
except :
# broken socket connection
socket.close()
# broken socket, remove it
if socket in SOCKET_LIST:
SOCKET_LIST.remove(socket)
if __name__ == "__main__":
sys.exit(chat_server())
Here is my client code.
# chat_client.py
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()
# TEST
person = raw_input ('Please enter your username: ')
print 'Connected to remote host. You can start sending messages.'
sys.stdout.write( person + '[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( person + '[Me]: '); sys.stdout.flush()
else :
# user entered a message
msg = sys.stdin.readline()
s.send(msg)
sys.stdout.write( person + '[Me]: '); sys.stdout.flush()
if __name__ == "__main__":
sys.exit(chat_client())
I'm currently trying to work on adding sort of a "handle" system into the chat client. If you were to run this code, you'll notice that the handle you choose is only displayed on your client, and not anybody else's. I've done hours of research already, and I can't for the life of me figure out how to have a client's chosen handle displayed onto other clients.
I'm still relatively new to Python, and especially new to TCP/IP programming. Any help, advice, and constructive criticism will be welcomed. Thanks in advance!
You can do it on the server or the client side
Server side
To implement it server side, you need to maintain some kind of mapping in the server between client sockets and handles, so that when you broadcast a message from a socket, you can retrieve its handle and prepend it to the message before sending.
In order to know the handle of the clients, they can send it to the server as the first message when they connect. The server will interpret this first message as the handle, and store it mapping it to the socket from what it has been received.
The advantage of this approach is that the server can validate the handle before it accepts it from the clients, and if it is already in use, reject the handle or abort the connection. Also, the clients cannot fake their handle later in the conversation, as it is the server that sends them.
Client side
This is the easiest implementation, as you only need to modify the client and prepend the handle before sending each message.
# user entered a message
msg = sys.stdin.readline()
s.send(person + ": " + msg)
sys.stdout.write( person + '[Me]: '); sys.stdout.flush()
The drawbacks of this approach are that a malicious client can fake the handle to pretend to be another person, and that two clients can have the same handle at the same time, making them indistinguishable from each other.
I have simple python server and client.
Server:
import SocketServer
import threading
class MyTCPHandler(SocketServer.BaseRequestHandler):
def handle(self):
self.data = self.request.recv(1024).strip()
print str(self.client_address[0]) + " wrote: "
print self.data
self.request.send(self.data.upper())
if __name__ == "__main__":
HOST, PORT = "localhost", 3288
server = SocketServer.TCPServer((HOST, PORT), MyTCPHandler)
server.serve_forever()
Client:
import socket
import sys
from time import sleep
HOST, PORT = "localhost", 3288
data = "hello"
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
sock.connect((HOST, PORT))
sock.send(data + "\n")
received = sock.recv(1024)
sleep(10)
sock.send(data + "\n")
received = sock.recv(1024)
sleep(10)
sock.send(data + "\n")
received = sock.recv(1024)
finally:
sock.close()
Here is the output I get:
Server:
>python server.py
127.0.0.1 wrote:
hello
Client:
>python client.py
Traceback (most recent call last):
File "client.py", line 18, in <module>
received = sock.recv(1024)
socket.error: [Errno 10053] An established connection was aborted by the software in your host machine
I tried it on a linux machine as well. The server only receives one message and then I get an error on the recv statement of second message. I have just started learning networking on python but I think the server is closing the socket for some reason. How do I correct this?
A MyTcpHandler object is created for each connection, and handle is called to deal with the client. The connection is closed when handle returns, so you have to handle the complete communication from the client within the handle method:
class MyTCPHandler(SocketServer.BaseRequestHandler):
def handle(self):
while 1:
self.data = self.request.recv(1024)
if not self.data:
break
self.data = self.data.strip()
print str(self.client_address[0]) + " wrote: "
print self.data
self.request.send(self.data.upper())
NOTE: recv returns '' when the client closes the connection, so I moved .strip() after the recv so there is no false alarm due to the client sending only white space.
I'll first admit that it's been years since I last used SocketServer, so there might be more idiomatic approaches to solve your problem.
Note that your client opens a single connection and sends three sets of data and receives three sets of data. (Hopefully the TCP stack will send buffered data once you call receive() on the socket.)
Your server is expecting to handle a client connection completely, from start to finish, when it is called from the SocketServer callback mechanism. Your current class does a little bit of IO and then quits. You just need to extend your server callback to do more:
class MyTCPHandler(SocketServer.BaseRequestHandler):
def handle(self):
self.data = self.request.recv(1024).strip()
print str(self.client_address[0]) + " wrote: "
print self.data
self.request.send(self.data.upper())
foo = self.request.recv(1024).strip()
self.request.send(foo.lower())
bar = self.request.recv(1024).strip()
self.request.send("goodbye " + bar)
TO a similar problem here error: [Errno 10053]
I also tried the same thing and got the same error.
If there is a simple code like this to demonstrate this error:
import socket
host = 'localhost'
port = 5001
size = 102400
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((host,port))
for msg in ['Hello, world','Test','anything goes here']:
s.send(msg)
data = s.recv(size)
print 'Received:', data
s.close()
If you create a socket object and the amt it can send and echo back from server to see how much it receivers, if you vary that, say 1024 to 102400(in this code);
Which means the socket should not get closed but again in my Windows OS, the server side keeps listening and printing any data that client sends but on the Client side you get this error;
However if it is that the client can connect only once and send and receive only once, then that is how it was designed. Trying this works without any errors:
for msg in ['Hello, world','Test','anything goes here']:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((host,port))
s.send(msg)
data = s.recv(size)
s.close()
print 'Received:', data
I am not sure if one socket object works only once to send and recieve data.
UPDATE
I think the issue was the capacity per client socket to receive data as per the buffersize fixed;
That's why the second code snippet above works thus creating new client connection sockets on the server. But that way lots of sockets are going to get used up.
Instead the following code fixed that problem by checking the amt of size being used up. If it exceeds the given amount, it creates a new socket at clients' but makes sure the message is sent; Actually the problem was with the server code but fixed it.
size = 10
This is a quick baby attempt at the code. I am sure you would understand and optimize it for the better!
client code:
messag = ['Hello, world', 'Test', 'anything goes here']
def client_to_server(messag,host,port,size):
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((host, port))
countmsg = 0
restmsg = ''
for msg in messag:
strl = tmsg = msg
if len(restmsg):
tmsg = restmsg + ' ' + msg
countmsg = len(tmsg)
if countmsg <= size:
pass
else:
restmsg = tmsg[size:]
tmsg = tmsg[:size]
#s.close()
countmsg = len(tmsg)
#s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
#s.connect((host, port))
print 'Sending to server msg {}'.format(tmsg)
s.send(tmsg)
# s.settimeout(1)
try:
data = s.recv(size)
print 'Received:', data
if strl == data:
print strl,data
countmsg = 0
restmsg = ''
except (socket.error), e:
print e.args,e.message
s.close()
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((host, port))
s.close()
if restmsg:
client_to_server([restmsg],host,port,size)
return
client_to_server(messag,host,port,size)
Server Code:
size = 1024 #This has to be bigger than client buf size!
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((host, port))
s.listen(backlog)
while True:
#this is what accepts and creates a P2P dedicated client socket per socket
client, address = s.accept()
try:
data = client.recv(size)
while data or 0:
print "Client sent {} | Server sending data to client address {}".format(data, address)
client.send(data)
data = client.recv(size)
else: client.close()
except (socket.error), e:
client.close()
print e.args, e.message
Try it out. This uses the same socket.