python multithreaded socket segmentation fault - python

I am currently programming a python socket server, which is working fine but with a big issue:
First here is the code
import socket
import threading
class ThreadedServer(object):
def __init__(self, host, port):
self.host = host
self.port = port
self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEPORT, 1)
self.sock.bind((self.host, self.port))
def listen(self):
self.sock.listen(6)
while True:
client, address = self.sock.accept()
client.settimeout(20)
threading.Thread(target=self.listenToClient, args=(client, address)).start()
def listenToClient(self, client, address):
size = 1024
while True:
try:
data = client.recv(size)
if data:
response = data
client.send(response)
print(response)
else:
raise
except:
client.close()
return False
if __name__ == "__main__":
while True:
port_num = input("Port: ")
try:
port_num = int(port_num)
break
except ValueError:
pass
ThreadedServer(ipaddress, port_num).listen()
The point is to have a socket server that can listen to multiple clients at the same time.
While i can connect to this socket with another python program, I am having an issue as soon as the socket.close() command came or the client program exits.
Segmentation fault (core dumped)
I assume the issue lies in the multithreading of the python code, however i am unfortunately not able to identify what i have to change to make it resistant to clients closing the socket or exiting the client program. Many stackoverflow answers are referring to C directly and not to python.
Any idea would be greatly appreciated
UPDATE:
rewriting the listen function to :
def listen(self):
# self.sock.listen(6)
while True:
self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
self.sock.bind((self.host, self.port))
self.sock.listen(6)
client, address = self.sock.accept()
client.settimeout(20)
threading.Thread(target=self.listenToClient, args=(client, address)).start()
did not help unfortunately
UPDATE2:
running the process in a single thread works (meaning: i replace the threading.Thread line with just a call to the listenToClient function)
I can then connect with a client script, close the connection and open it again.

Related

Blocking socket, possible to solve with multiprocessing?

I'm trying to learn some basic socket programming in python. What i would like to do is have a seperate thread that activliy listens for network activity while my main program does something else.
What I don't understand is why the while(True) loop in the code below never runs. Should it not be on a seperate thread from the socket?
import socket
import multiprocessing
def waitForConnection():
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
port = 8000
address = ''
server_socket.bind((address, port))
server_socket.listen(0)
client_socket, client_ip = server_socket.accept()
client_conn = client_socket.makefile(mode='rwb')
process = multiprocessing.Process(target=waitForConnection())
process.start()
#main program
while(True):
print("I never reach this line when no client is connected")

create multi-thread tcp server python 3

Hello I tried to make a simple server that accept multiple clients simultaneously I'm new to python and I have a difficult to understand it....I try to change my code in multi-thread applications but without positive result...here is the code:
import socket, threading
def message():
while 1:
data = connection.recv(1024)
if not data: break
#connection.sendall(b'-- Message Received --\n')
print(data.decode('utf-8'))
connection.close()
def connection():
address = input("Insert server ip")
port = 44444
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((address, port))
s.listen(1)
print("Server started! Waiting for connections...")
def accept connection():
connection, address = s.accept()
print('Client connected with address:', address)
t=thread.Threading(target=message,args=(connection))
t.run()
I know that there are many errors but I'm new in python sorry :(
The original non-threaded code is:
import socket
address = input("Insert server ip:")
port = 44444
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((address, port))
s.listen(1)
print("Server started! Waiting for connections...")
connection, address = s.accept()
print('Client connected with address:', address)
while 1:
data = connection.recv(1024)
if not data: break
#connection.sendall(b'-- Message Received --\n')
print(data.decode('utf-8'))
connection.close()
Your basic design is close, but you've got a whole lot of little problems making it hard to move forward.
First, you have a function name with a space in it, which isn't allowed. And you have an IndentationError because you didn't indent its contents.
Next, inside that accept_connection function, you're using threading wrong.
thread.Threading doesn't exist; you probably meant threading.Thread.
args has to be a sequence (tuple, list, etc.) of values. You probably expected (connection) to be a tuple of one value, but it's not; tuples are defined by commas, not parentheses, and what you have is just the value connection with superfluous parentheses around it. You wanted (connection,) here.
Also, calling run on a thread object just runs the thread's code in the current thread. You want to call start, which will start a new thread and call the run method on that thread.
Meanwhile, you're never actually calling this function anywhere, so of course it can't do anything. Think about where you want to call it. After creating the listener socket, you want to loop around accept, kicking off a new client thread for each accepted connection, right? So, you want to call it in a loop, either inside connection, or at the top level (in which case connection has to return s).
And finally, your accept_connection function can't access local variables from some other function; if you want it to use a socket named s, you have to pass it as a parameter.
So:
def connection():
address = input("Insert server ip")
port = 44444
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((address, port))
s.listen(1)
print("Server started! Waiting for connections...")
while True:
accept_connection(s)
def accept_connection(s):
connection, address = s.accept()
print('Client connected with address:', address)
t=thread.Threading(target=message, args=(connection,))
t.start()
As a side note, be careful with using sock.recv(1024) and assuming you're going to get the whole message that the other side sent with send(msg). You might get that, or you might get half the message, or the whole message plus half of another message the client sent later. Sockets are just streams of bytes, like files, not streams of separate messages; you need some kind of protocol to separate messages.
The simplest possible protocol is to send each message on its own line. Then you can just do socket.makefile() and for line in f:, just like you would for a real file. Of course this doesn't work if your messages can have newlines, but you can, e.g., backslash-escape them on one side and unescape them on the other.
This is a pretty old post but there's a nice way to do what you're talking about. Here's a link to an example I posted a little while back:
https://bitbucket.org/matthewwachter/tcp_threadedserver/src/master/
And the script:
from datetime import datetime
from json import loads, dumps
from pprint import pprint
import socket
from threading import Thread
class ThreadedServer(Thread):
def __init__(self, host, port, timeout=60, debug=False):
self.host = host
self.port = port
self.timeout = timeout
self.debug = debug
Thread.__init__(self)
# run by the Thread object
def run(self):
if self.debug:
print(datetime.now())
print('SERVER Starting...', '\n')
self.listen()
def listen(self):
# create an instance of socket
self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
# bind the socket to its host and port
self.sock.bind((self.host, self.port))
if self.debug:
print(datetime.now())
print('SERVER Socket Bound', self.host, self.port, '\n')
# start listening for a client
self.sock.listen(5)
if self.debug:
print(datetime.now())
print('SERVER Listening...', '\n')
while True:
# get the client object and address
client, address = self.sock.accept()
# set a timeout
client.settimeout(self.timeout)
if self.debug:
print(datetime.now())
print('CLIENT Connected:', client, '\n')
# start a thread to listen to the client
Thread(target = self.listenToClient,args = (client,address)).start()
# send the client a connection message
# res = {
# 'cmd': 'connected',
# }
# response = dumps(res)
# client.send(response.encode('utf-8'))
def listenToClient(self, client, address):
# set a buffer size ( could be 2048 or 4096 / power of 2 )
size = 1024
while True:
try:
# try to receive data from the client
data = client.recv(size).decode('utf-8')
if data:
data = loads(data.rstrip('\0'))
if self.debug:
print(datetime.now())
print('CLIENT Data Received', client)
print('Data:')
pprint(data, width=1)
print('\n')
#send a response back to the client
res = {
'cmd': data['cmd'],
'data': data['data']
}
response = dumps(res)
client.send(response.encode('utf-8'))
else:
raise error('Client disconnected')
except:
if self.debug:
print(datetime.now())
print('CLIENT Disconnected:', client, '\n')
client.close()
return False
if __name__ == "__main__":
ThreadedServer('127.0.0.1', 8008, timeout=86400, debug=True).start()
Here is some example code I have showing a threaded socket connection.
def sock_connection( sock, host ):
"Handle socket"
pass
while 1:
try:
newsock = sock.accept()
thread = Thread( target=sock_connection, args=newsock )
thread.start()
except Exception, e:
print "error on socket connection: " % e)

Python server programming

I am trying a little client server project to get me into network programming but I seem to have got stuck at the first hurdle. I cant seem to get past getting the first line of data only even if its a new connection.
#!/usr/bin/python
import socket
s = socket.socket()
host = '192.168.0.233' # Test Server
port = 7777
s.bind((host, port))
s.listen(5)
while True:
c, addr = s.accept()
print 'Got connection from', addr
data = c.recv(2048)
print(data)
If I telnet to the host running the server, the connection opens fine and I see on the server Got connection from addr, but I also only see the first line of data when I sent 4 lines of data,
I thought because its in a loop it should now always be looking for data?
I know im doing something wrong but unsure what.
Im using Python 2.6.6
recv needs to be in a loop too, at the moment your code is receiving some data and then waiting for a new connection.
https://docs.python.org/2/library/socket.html#example has an example of socket.recv in a loop.
Try this:
#!/usr/bin/python
import socket
import threading
def listenForClients(sock):
while True:
client, address = sock.accept()
client.settimeout(5)
threading.Thread( target = listenToClient, args = (client,address) ).start()
def listenToClient(client, address):
size = 2048
while True:
try:
data = client.recv(size)
if data:
response = "Got connection"
client.send(response)
else:
raise error('Client disconnected')
except:
client.close()
return False
def main(host, port):
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sock.bind((host, port))
sock.listen(5)
listenForClients(sock)
if __name__ == "__main__":
main('192.168.0.233',7777)
Here I use a thread for each client. The problem that you have with having Socket.accept() in the loop is that it blocks meaning that concurrent access won't work and you'll only be able to talk to one client at a time.
Try running it in the background and sending it messages with:
#!/usr/bin/python
import socket
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect(('192.168.0.233',7777))
vwhile True:
data = raw_input("enter a message: ")
sock.send(data)
print sock.recv(2048)

Sending string via socket (python)

I have two scripts, Server.py and Client.py.
I have two objectives in mind:
To be able to send data again and again to server from client.
To be able to send data from Server to client.
here is my Server.py :
import socket
serversocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
host = "192.168.1.3"
port = 8000
print (host)
print (port)
serversocket.bind((host, port))
serversocket.listen(5)
print ('server started and listening')
while 1:
(clientsocket, address) = serversocket.accept()
print ("connection found!")
data = clientsocket.recv(1024).decode()
print (data)
r='REceieve'
clientsocket.send(r.encode())
and here is my client :
#! /usr/bin/python3
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
host ="192.168.1.3"
port =8000
s.connect((host,port))
def ts(str):
s.send('e'.encode())
data = ''
data = s.recv(1024).decode()
print (data)
while 2:
r = input('enter')
ts(s)
s.close ()
The function works for the first time ('e' goes to the server and I get return message back), but how do I make it happen over and over again (something like a chat application) ?
The problem starts after the first time. The messages don't go after the first time.
what am I doing wrong?
I am new with python, so please be a little elaborate, and if you can, please give the source code of the whole thing.
import socket
from threading import *
serversocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
host = "192.168.1.3"
port = 8000
print (host)
print (port)
serversocket.bind((host, port))
class client(Thread):
def __init__(self, socket, address):
Thread.__init__(self)
self.sock = socket
self.addr = address
self.start()
def run(self):
while 1:
print('Client sent:', self.sock.recv(1024).decode())
self.sock.send(b'Oi you sent something to me')
serversocket.listen(5)
print ('server started and listening')
while 1:
clientsocket, address = serversocket.accept()
client(clientsocket, address)
This is a very VERY simple design for how you could solve it.
First of all, you need to either accept the client (server side) before going into your while 1 loop because in every loop you accept a new client, or you do as i describe, you toss the client into a separate thread which you handle on his own from now on.
client.py
import socket
s = socket.socket()
s.connect(('127.0.0.1',12345))
while True:
str = raw_input("S: ")
s.send(str.encode());
if(str == "Bye" or str == "bye"):
break
print "N:",s.recv(1024).decode()
s.close()
server.py
import socket
s = socket.socket()
port = 12345
s.bind(('', port))
s.listen(5)
c, addr = s.accept()
print "Socket Up and running with a connection from",addr
while True:
rcvdData = c.recv(1024).decode()
print "S:",rcvdData
sendData = raw_input("N: ")
c.send(sendData.encode())
if(sendData == "Bye" or sendData == "bye"):
break
c.close()
This should be the code for a small prototype for the chatting app you wanted.
Run both of them in separate terminals but then just check for the ports.
This piece of code is incorrect.
while 1:
(clientsocket, address) = serversocket.accept()
print ("connection found!")
data = clientsocket.recv(1024).decode()
print (data)
r='REceieve'
clientsocket.send(r.encode())
The call on accept() on the serversocket blocks until there's a client connection. When you first connect to the server from the client, it accepts the connection and receives data. However, when it enters the loop again, it is waiting for another connection and thus blocks as there are no other clients that are trying to connect.
That's the reason the recv works correct only the first time. What you should do is find out how you can handle the communication with a client that has been accepted - maybe by creating a new Thread to handle communication with that client and continue accepting new clients in the loop, handling them in the same way.
Tip: If you want to work on creating your own chat application, you should look at a networking engine like Twisted. It will help you understand the whole concept better too.

Python Socket Listening

All of the below mentioned is on windows machines using python 2.7
Hello,
I am currently attempting to listen on a socket for data send by a remote program. This data is then printed to the screen and user input is requested that is then returned to remote program. In testing I have been able to have the remote program send me a menu of command line programs (cmd, ipconfig, whoami, ftp) and then my program returns with a number as a selection of the menu option.
The remote program receives my response and sends the output of the selected command. ipconfig and whoami work perfectly, but cmd and ftp only returns the output of the terminal once. (I.E. I can enter one command into the FTP program and send that too the remote program before I never hear back)
The part of my code that fails is that
if ready[0]: never becomes ready a second time after the first conversation.
I know the remote program is functioning correctly as I can use netcat to act in lieu of my code and operate the cmd terminal indefinitely.
How do I go about properly implementing a python socket listener that can account for this type of connection?
My "program" in its entirety:
import socket, sys, struct, time, select
host = ''
port = 50000
connectionSevered=0
try:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
except socket.error:
print 'Failed to create socket'
sys.exit()
print '[+] Listening for connections on port '+str(port)+'.'
s.bind((host,port))
s.listen(5)
def recvall(the_socket,timeout=2):
global connectionSevered
data=''; # Data found by recv
total_data=[]; # Finally list of everything
s.setblocking(0) #make socket non blocking
begin=time.time() #beginning time
while 1:
ready = select.select([client], [], [], .2)
if time.time()-begin > timeout:
print 'Timeout reached'
#Leave loop, timer has reached its threshold
break
if ready[0]:
print 'In ready loop!'
try:
data = client.recv(4096) #attempt to fetch data
if data:
begin=time.time() #reset timeout timer
total_data.append(data)
data='';
except socket.error:
print '[+] Lost connection to client. Printing buffer...'
connectionSevered=1 # Let main loop know connection has errored
pass
time.sleep(1)
#join all parts to make final string
return ''.join(total_data)
client, address = s.accept()
print '[+] Client connected!'
while (connectionSevered==0): # While connection hasn't errored
print "connectionSevered="+str(connectionSevered) # DEBUG
recvall(s)
response = raw_input() #take user input
client.sendto(response) #send input
client.close(0)
Please let me know if you need more information, any help would be greatly appreciated, I am very new to this and eager to learn.
Playing around with this for a while finally got it working nice with a telnet session locally using python 2.7.
What it does is it sets up a thread that runs when the client connects listening for client stuff.
When the client sends a return ("\r\n" might have to change that if your interacting with a Linux system?) the message gets printed to the server, while this is happening if there is a raw input at the server side this will get sent to the client:
import socket
import threading
host = ''
port = 50000
connectionSevered=0
class client(threading.Thread):
def __init__(self, conn):
super(client, self).__init__()
self.conn = conn
self.data = ""
def run(self):
while True:
self.data = self.data + self.conn.recv(1024)
if self.data.endswith(u"\r\n"):
print self.data
self.data = ""
def send_msg(self,msg):
self.conn.send(msg)
def close(self):
self.conn.close()
try:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((host,port))
s.listen(5)
except socket.error:
print 'Failed to create socket'
sys.exit()
print '[+] Listening for connections on port: {0}'.format(port)
conn, address = s.accept()
c = client(conn)
c.start()
print '[+] Client connected: {0}'.format(address[0])
c.send_msg(u"\r\n")
print "connectionSevered:{0}".format(connectionSevered)
while (connectionSevered==0):
try:
response = raw_input()
c.send_msg(response + u"\r\n")
except:
c.close()
The above answer will not work for more than a single connection. I have updated it by adding another thread for taking connections. It it now possible to have more than a single user connect.
import socket
import threading
import sys
host = ''
port = 50000
class client(threading.Thread):
def __init__(self, conn):
super(client, self).__init__()
self.conn = conn
self.data = ""
def run(self):
while True:
self.data = self.data + self.conn.recv(1024)
if self.data.endswith(u"\r\n"):
print self.data
self.data = ""
def send_msg(self,msg):
self.conn.send(msg)
def close(self):
self.conn.close()
class connectionThread(threading.Thread):
def __init__(self, host, port):
super(connectionThread, self).__init__()
try:
self.s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.s.bind((host,port))
self.s.listen(5)
except socket.error:
print 'Failed to create socket'
sys.exit()
self.clients = []
def run(self):
while True:
conn, address = self.s.accept()
c = client(conn)
c.start()
c.send_msg(u"\r\n")
self.clients.append(c)
print '[+] Client connected: {0}'.format(address[0])
def main():
get_conns = connectionThread(host, port)
get_conns.start()
while True:
try:
response = raw_input()
for c in get_conns.clients:
c.send_msg(response + u"\r\n")
except KeyboardInterrupt:
sys.exit()
if __name__ == '__main__':
main()
Clients are not able to see what other clients say, messages from the server will be sent to all clients. I will leave that as an exercise for the reader.
If you're in Python 3 by now and still wondering about sockets, here's a basic way of using them:
server.py
import time
import socket
# creating a socket object
s = socket.socket(socket.AF_INET,
socket.SOCK_STREAM)
# get local Host machine name
host = socket.gethostname() # or just use (host == '')
port = 9999
# bind to pot
s.bind((host, port))
# Que up to 5 requests
s.listen(5)
while True:
# establish connection
clientSocket, addr = s.accept()
print("got a connection from %s" % str(addr))
currentTime = time.ctime(time.time()) + "\r\n"
clientSocket.send(currentTime.encode('ascii'))
clientSocket.close()
client.py
import socket
# creates socket object
s = socket.socket(socket.AF_INET,
socket.SOCK_STREAM)
host = socket.gethostname() # or just use (host = '')
port = 9999
s.connect((host, port))
tm = s.recv(1024) # msg can only be 1024 bytes long
s.close()
print("the time we got from the server is %s" % tm.decode('ascii'))
Run server.py first, then run client.py.
This is just send and receive the currentTime.
What's new in Python 3.4 sockets?
A major difference between python 2.7 sockets and python 3.4 sockets is the sending messages. you have to .encode() (usually using 'ascii' or blank as parameters/arguments)
and then using .decode()
For example use .encode() to send, and use .decode() to receive.
Extra info: client/server socket tutorial

Categories