IndexError: list index out of range Multi-threaded server - python

from socket import *
import thread
def thread_handler(connectionSocket, addr):
while True:
# Establish the connection
print ("Ready to serve...")
# connectionSocket, addr = serverSocket.accept()
try:
message = connectionSocket.recv(1024)
# print(message, '::', message.split()[0], ":", message.split()[1])
filename = message.split()[1]
# print(filename, "||", filename[1:])
f = open(filename[1:], "r")
outputdata = f.read()
# print(outputdata)
#Send one HTTP header line into socket
#Fill in start
connectionSocket.send('\nHTTP/1.1 200 OK\n\n')
connectionSocket.send(outputdata)
#Fill in end
#Send the content of the requested file to the client
for i in range(0,len(outputdata)):
connectionSocket.send(outputdata[i:i+1])
connectionSocket.send(b'\r\n\r\n')
except IOError:
#Send response message for file not found
#Fill in Start
connectionSocket.send('\nHTTP/1.1 404 Not Found\n\n')
#Fill in end
#Close client socket
if __name__ == '__main__':
serverSocket = socket(AF_INET, SOCK_STREAM)
# Prepare a sever socket
serverSocket.bind(("localhost", 6789))
serverSocket.listen(1)
while True:
print('waiting for connection...')
connectionSocket, addr = serverSocket.accept()
print('...connected from:', addr)
thread.start_new_thread(thread_handler, (connectionSocket, addr))
serverSocket.close()
I understand how the multi threading works now, but I could not figure out how to build a connection.
I'm trying to do a multi-threaded version of TCP server. However, it keeps giving "list index out of range":
Ready to serve...
Unhandled exception in thread started by <function thread_handler at 0x10b9750c8>
Traceback (most recent call last):
File "http_server_multi.py", line 16, in thread_handler
filename = message.split()[1]
IndexError: list index out of range

If nothing is received from the socket because there is no data yet, the split() will return [''] with only on item and the [1] on it will fail.
Try to add this before the failing line
if not message:
# time.sleep(0.01)
continue
The sleep() call will prevent the thread to use too much CPU, you can umcomment it and adapt the value to your needs.

Related

Python socket programming: ConnectionRefusedError: [Errno 111] Connection refused

I am sending ssh count data from 'alphaclient' to 'alphaserver'. However the alphaclient server is not able to connect with alphaserver. Kindly help me resolve this error. I tried to kill the process at the port and restart the VMs but still getting the same issue.
This is the error output in alphaclient:
Traceback (most recent call last):
File "//./sshlogin-counter/alphaclient.py", line 82, in <module>
inform_alphaserver(client_message)
File "//./sshlogin-counter/alphaclient.py", line 45, in inform_alphaserver
c.connect((alphaserver_ip,port))
ConnectionRefusedError: [Errno 111] Connection refused
and this is the output in alphaserver:
Binding alphaserver at port 7888
Server Socket created.
Server socket binded at port 7888
Listening to port...
alphaclient.py
import os
import socket
input_file = os.path.join('/','var', 'log', 'auth.log')
#output_file = os.path.join('.','sshlogin-counter','client_message.txt')
total_ssh_attempts = 0
#Function1 that reads /var/log/auth.log and returns total ssh attempts made into that VM
def ssh_attempts(input_file):
successful_ssh_attempts = 0
invalid_ssh_attempts = 0
current_ssh_attempts = 0
with open(input_file,'r') as f:
f = f.readlines() #list of lines
for line in f:
if 'sshd' and 'Accepted publickey' in line:
successful_ssh_attempts+=1
#elif 'sshd' and 'Invalid user' in line:
#invalid_ssh_attempts+=1
current_ssh_attempts = successful_ssh_attempts + invalid_ssh_attempts
return (current_ssh_attempts)
#Function2 that informs Alphaserver of new ssh login attempts
def inform_alphaserver(client_message):
port = 7888
alphaserver_hostname = socket.gethostname()
alphaserver_ip = socket.gethostbyname(alphaserver_hostname)
print('Establishing connection with {} at port {} ...'.format(alphaserver_ip,port))
c = socket.socket()
print('Client socket created...')
c.connect((alphaserver_ip,port))
print('Client socket connected with {} at port {}'.format(alphaserver_ip, port))
client_message = client_message.encode()
print("Sending client message...")
c.send(client_message)
print("Message has been transmitted to alphaserver successfully")
c.close()
print("Connection Closed!!!")
#Monitor new ssh login attempts
while True:
#Function 1
current_ssh_attempts = ssh_attempts(input_file)
#Condition to test if new login attempts made
if current_ssh_attempts > total_ssh_attempts:
total_ssh_attempts = current_ssh_attempts
print('SSH login attempts detected!!!')
client_message = '{} had {} attempt'.format(socket.gethostname(), total_ssh_attempts)
#Function 2
#Send output file to Alphaserver
inform_alphaserver(client_message)
alphaserver.py
import os
import socket
#File for storing messages from Alphaclient
client_messages = os.path.join ('.','sshlogin-counter','client_messages.txt')
#Function that listens to client servers and receives client data
def receive_clientmessage():
port = 7888
host = socket.gethostname()
print('Binding {} at port {}'.format(host,port))
s = socket.socket()
print('Server Socket created.')
s.bind((host, port))
print('Server socket binded at port {}'.format(port))
s.listen(2)
print('Listening to port...')
while True:
c , addr = s.accept()
print("Connected with {}".format(addr))
client_message = c.recv(1024).decode()
client_hostname = list(str(client_message).split(" "))[0] #str converted to list and list[0] is the client_hostname
print("Client host name is {} ".format(client_hostname))
c.close()
break
#s.close()
return (client_hostname, client_message)
#Function to write client data to client_message.
def update_client_messages(client_hostname, client_message):
file = open(client_messages, 'r+')
f = file.read()
if client_hostname in f:
position = f.index(client_hostname)
file.seek(position)
file.write(str(client_message))
print('Updated client SSH login data')
file.close()
else:
file = open(client_messages,'a')
file.write('\n'+ str(client_message))
print('Added new client SSH login data')
file.close()
#Continuosly monitor and display client data
while True:
client_hostname, client_message = receive_clientmessage()
update_client_messages(client_hostname, client_message)
file = open(client_messages)
content = file.read()
print('----------------------------------------------------')
print(content)
print('----------------------------------------------------')
file.close()

No attribute to append socket python

I'm creating a simple chat server and when I try to connect a client I get this error:
Traceback (most recent call last):
File "C:\Users\OneDrive\Desktop\Py Files\chat_server.py", line 47, in <module>
recive()
File "C:\Users\OneDrive\Desktop\Py Files\chat_server.py", line 39, in recive
client.append(client)
AttributeError: 'socket' object has no attribute 'append'
Here is my code:
import threading
import socket
host = '127.0.0.1'
port = 20200
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind((host, port))
server.listen()
clients = []
nicknames = []
def brodcast(message):
for client in clients:
client.send(message)
def handle(client):
while True:
try:
message = client.recv(1024)
brodcast(message)
except:
index = clients.index(client)
clients.remove(client)
client.close()
nickname = nicknames[index]
brodcast(f'{nickname} left the chat'.encode('ascii'))
nicknames.remove(nickname)
break
def recive():
while True:
client, address = server.accept()
print(f"Connected with {str(address)}")
client.send('NICK'.encode('ascii'))
nickname = client.recv(1024).decode('ascii')
nicknames.append(nickname)
client.append(client)
print(f'{nickname} joined the chat!')
brodcast(f'{nickname} joined the chat!')
client.send('Connected to the chat')
thread = threading.Thread(target=handle, args=(client,))
thread.start()
recive()
I've provided the code for the server because that is where the error is. On the client end, there appears to be no issues.

Python socket: [Errno 107] Transport endpoint is not connected

I'm trying to hack together a way to send messages between two computers. The following code creates a thread for receiving messages.
import socket # Import socket module
import threading
import traceback
def recv_one_message(sock):
lengthbuf = recvall(sock, 4)
length, = struct.unpack('!I', lengthbuf)
return recvall(sock, length)
def recvall(sock, count):
buf = b''
while count:
newbuf = sock.recv(count)
if not newbuf: return None
buf += newbuf
count -= len(newbuf)
return buf
host="ec2-35-160-33-3.us-west-2.compute.amazonaws.com"
kill_threads=False
def receive_thread():
while not kill_threads:
try:
# Create a socket object
soc = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
soc.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
port = 8502 # Reserve a port for your service.
soc.bind((host, port)) # Bind to the port
print("port bound")
soc.settimeout(10)
soc.listen(50000000) # Now wait for client connection.
conn, addr = soc.accept() # Establish connection with client.
soc.settimeout(None)
print ("Got connection from",addr)
while not kill_threads:
msg_binary=recv_one_message(soc)
msg=str(msg_binary, "utf-8")
print(msg)
except Exception:
traceback.print_exc()
try:
conn.close()
soc.close()
except Exception:
traceback.print_exc()
t2 = threading.Thread(target=receive_thread)
t2.daemon=True
t2.start()
I get the following error:
Traceback (most recent call last):
File "<ipython-input-3-eaef71a53845>", line 59, in receive_thread
msg_binary=recv_one_message(soc)
File "<ipython-input-3-eaef71a53845>", line 7, in recv_one_message
lengthbuf = recvall(sock, 4)
File "<ipython-input-3-eaef71a53845>", line 14, in recvall
newbuf = sock.recv(count)
OSError: [Errno 107] Transport endpoint is not connected
Here is my Scala sender that tries to connect to the Python part and sends "hello world" once a second.
import java.io._
import java.net._
import java.nio.charset.Charset
val host = "ec2-35-160-33-3.us-west-2.compute.amazonaws.com"
new Thread {
override def run() {
while (true) {
try {
print("trying to establish connection")
val soc = new Socket(host, 8502)
val dout = new DataOutputStream(soc.getOutputStream())
print("connection established")
val serializedMessage = "hello world"
val serializedMessageBytes = (serializedMessage).getBytes(Charset.forName("UTF-8"))
while (true) {
dout.write(serializedMessageBytes.length)
dout.write(serializedMessageBytes)
dout.flush()
Thread.sleep(1000)
}
} catch {
case e => e.printStackTrace()
}
}
}
}.start()
conn, addr = soc.accept() # Establish connection with client.
...
msg_binary=recv_one_message(soc)
You need to receive the data on the connected socket you got from accept (conn) and not on the listener socket (soc).

How to detect when a client disconnects from a UDS (Unix Domain Socket)

When a client connects to the pipe, and sends data I can receive this fine and I can keep receiving the data. Trouble comes when the client disconnects and the while loop is still active, connection.recv() doesn't block and therefore keeps looping frantically! So I need a way to detect if a client is still connected.
I have the following code:
pipe = './pipes/uds_defzone-lrecv'
try:
os.unlink(pipe)
except OSError:
if os.path.exists(pipe):
raise
self.logger.debug('Created UDS pipe: ' + pipe)
sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
sock.bind(pipe)
sock.listen(1)
self.logger.debug('Waiting for connection: ' + pipe)
connection, client_address = sock.accept()
self.logger.debug('Connection from: ' + client_address)
while True:
self.logger.debug('Waiting for data')
data = connection.recv(4096)
self.logger.debug('Received: ' + str(data))
For reference, the sender.py code:
# Create a UDS socket
sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
# Connect the socket to the port where the server is listening
pipe = './pipes/uds_defzone-lrecv'
logger.debug('connecting to: ' + pipe)
try:
sock.connect(pipe)
except socket.error, msg:
logger.debug(msg)
sys.exit(1)
try:
message = 'THIS IS A TEST'
logger.debug('sending: ' + message)
sock.sendall(message)
time.sleep(2)
finally:
logger.debug('closing socket')
sock.close()
TIA!
UPDATE
I can slow it down with the following code I suppose, but not exactly what I want.
while True:
try:
self.logger.debug('Waiting for data')
data_present = select.select([sock], [], [], 30)
if data_present[0]:
data = connection.recv(4096)
self.logger.debug('Received: ' + data)
except select.timeout:
pass
UPDATE 2
For reference this is the code I came up with:
while True:
logger.debug('Waiting for data')
data = connection.recv(4096)
if not data == '':
logger.debug('Received: ' + data)
else:
logger.debug('Nothing received')
break
A hack I came up with in the process... Might be usable where it is legitimate that a client might send empty data, for signalling perhaps?
while True:
try:
logger.debug('Waiting for data')
data = connection.recv(4096)
# *** This throws an exception when client has disconnected
x = connection.getpeername()
logger.debug('Received: ' + data)
except:
logger.debug('Client disconnected')
break
connection.recv() doesn't block and therefore keeps looping frantically! So I need a way to detect if a client is still connected.
If the peer disconnects recv data will return empty data (''). You need to check this and exit the loop.

python socket, how to receive all the message when buffer is not big enough?

# addition_server.py
import socket
buf_size = 4
host = ''
port = 8000
server_addr = (host, port)
def get_msg(soc):
msg = ''
while True:
temp = soc.recv(buf_size)
if not temp:
break
msg += temp
return msg
if __name__ == '__main__':
soc = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# socket.error: [Errno 98] Address already in use
soc.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
soc.bind(server_addr)
soc.listen(0)
runnnig = True
while runnnig:
client_soc, client_addr = soc.accept()
print client_addr
# socket.error: [Errno 104] Connection reset by peer
message = client_soc.recv(buf_size)
#message = get_msg(client_soc)
if message == 'q':
runnnig = False
numbers = message.split(' ')
numbers = filter(None, numbers)
try:
numbers = map(int, numbers)
s = sum(numbers)
numbers = map(str, numbers)
answer = ' + '.join(numbers)
answer = '%s = %s' % (answer, s)
except Exception as e:
print e
answer = 'error'
client_soc.sendall(answer)
client_soc.close()
soc.close()
# addition_client.py
import socket
from addition_server import get_msg
from addition_server import server_addr
buf_size = 1
runnnig = True
while runnnig:
soc = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
soc.bind(('', 6060)) # without this, random port will be assigned
soc.connect(server_addr)
msg = raw_input('> ')
if not msg:
soc.close()
break
else:
if msg == 'q':
runnnig = False
soc.sendall(msg)
#reply = soc.recv(buf_size)
# socket.error: [Errno 104] Connection reset by peer
reply = get_msg(soc)
print reply
soc.close()
~/nuts/git/socket_learn/pairs$ python addition_client.py
> 1 2
1 + 2 = 3
> 1 2 3
Traceback (most recent call last):
File "addition_client.py", line 23, in <module>
reply = get_msg(soc)
File "/home/phy/nuts/git/socket_learn/pairs/addition_server.py", line 14, in get_msg
temp = soc.recv(buf_size)
socket.error: [Errno 104] Connection reset by peer
The buffer size in the server is intentionally small, so the you can see the above error.
but the get_msg(client_soc) method not works in the server, I don't know why.
The socket stream protocol implements a stream and there are no implicit message boundaries.
There is no way for the reader to know if a message is complete or not except if this is specified in the message content itself. No extra boundaries are added on the wire.
When you call recv and there is no data in the buffer the call will either raise an exception (non-blocking socket) or will just wait (blocking socket).
The sendall facility is just for avoiding writing a loop when sending a buffer but of course there is no way to implement recvall because there's no way to know when the message is complete.
You need to add a message boundary to your protocol; this could be a newline separating messages or prefixing each message with a message size. This way the reader will know when a message is complete before starting processing.

Categories