Socket programming questions [conceptual] - python

I am extremely new to sockets and have been doing a small project based on python.
I've written a simple script, which is this :
def runserver():
try:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
except socket.error, msg:
print(msg[0])
s.bind((host, port))
s.listen(10)
while True:
client, address = s.accept()
# !clients.append(client)
request = client.recv(1024)
params = request.split("|")
if params[0] == "reg_user":
print(params[1] + ", " + params[2])
client.send("Registration Request Received.")
elif params[0] == "login":
print(params[1] + ", " + params[2])
client.send("Login Request Received.")
# !Handles administrative login
elif params[0] == "admin_login":
print("Administrator requested login.")
res = admin_login(params[1], params[2])
if res == 1:
client.send("Login Successful!")
print("Login Successful!")
else:
client.send("Login Failed!")
print("Login Failed!")
client.close()
s.close()
# !main function
if __name__ == "__main__":
runserver()
My Question is, the line
client.close()
Does this line hamper the performance of the code ?
What I mean is, each time a socket connection is made, it is catered to, and then disconnected. This means, that if the application needs further communication, it needs to reconnect to the socket before doing any further business.
I need to know if this hampers the performance and if so, how to get past this ? I want to use persistent connection basically, i.e after login (successful), there will be no disconnection and the application (client) and server can talk uninterrupted.
The second part of the question is :
s.listen(10)
I am allowing a backlog of 10 connections. What is the threshold value for this backlog ? How many connection can a server usually handle in a real life situation ?

Related

Recieved [Error data].. Socket programming in python

I amusing a client to send a message to a python server.
client side: client.send("1")
Server side:
d=clientsocket.recv(1024)
if (d=="1"):
print(" Correct value")
It won't print correct value. I know the error at recv as I don't know how it works. Could anyone please help me to solve this matter.
You just need simple modification to work it correctly:-
in client correct like below:-
client.send("1".encode())
in server correct like below:-
d=clientsocket.recv(1024).decode()
if (d=="1"):
print(" Correct value")
I have created one client and server for you which is working fine in Python 3.4. Please try and check:
Here is your server
import socket
import sys
HOST = "localhost"
PORT = 8000
print("Creating socket...")
sc = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
print("Binding socket...")
try:
sc.bind((HOST, PORT))
except socket.error as err:
print("Error binding socket, {}, {}".format(err[0], err[1]))
print("bound Successful")
# Configure below how many client you want that server can listen to simultaneously
sc.listen(2)
print("Server is listening on {}:{}".format(HOST, PORT))
while True:
conn, addr = sc.accept()
print("Connection from: " + str(addr))
print("Receiving data from client\n")
data = conn.recv(1024).decode()
print("Client says :" + data)
if(data == "2"):
print(" Ooh you are killing me with value :" + data)
conn.sendall(str.encode("\n I am server and you killed me with :" + data))
break;
elif(data == "1"):
print(" Correct value :" + data)
conn.sendall(str.encode("\n I am server and you hit me with correct value:" + data))
else:
print(" You are sending a wrong value :" + data)
conn.sendall(str.encode("\n I am server and you hit me with wrong value :" + data))
sc.close()
and now your client is here:-
import socket
import sys
HOST = "localhost"
PORT = 8000
print("creating socket")
sc = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
print("Connecting to host")
try:
sc.connect((HOST, PORT))
except socket.error as err:
print("Error: could not connect to host, {}, {}".format(err[0], err[1]))
sys.exit()
print("Connection established to host")
message = "1" # Run client 3 times with value message = '1' and '5' and '2'
sc.send(message.encode())
data = sc.recv(1024).decode()
print("Server response is : " + data)
sc.close()

Server do not response to multiple request from one client

I try to implement a server which only responds to one client at a time and client side. For the client side, I only used one connection and can send multiple requests to server. For the first request, everything goes well. For all the requests after the first one, the client will report error: socket.error: [Errno 10053] An established connection was aborted by the software in your host machine
. I post my server and client code along with the sample test below:
The server part:
import socket
import re
#create server socket. AF_INET-> ipv4. SOCK_STREAM->socket type
serverSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
port = 20000
#bind the socket to localhost and a well-know port
serverSocket.bind((socket.gethostname(), port))
serverSocket.listen(3)
while True:
clientSocket, addr = serverSocket.accept()
print("Got a connection from %s" % str(addr))
request = clientSocket.recv(1024).decode()
print('Server received', repr(request))
splitRequest = re.split('\<|\>', request)
if splitRequest[0] == 'EXIT':
if len(splitRequest) == 1:
print "Normal exit"
elif len(splitRequest) > 1:
print splitRequest[1]
else:
if splitRequest[0] == 'GET':
fileName = splitRequest[1]
path = 'test_files/' + fileName
try :
with open(path, 'r') as serverFile:
message = serverFile.read()
print message
clientSocket.send(message)
except Exception as e:
message = str(e)
print message
clientSocket.send(message)
elif splitRequest[0] == 'BOUNCE':
message = splitRequest[1]
print message
clientSocket.sendall(message)
clientSocket.close()
The client side:
import socket
import re
def isValidRequest(input):
if re.match('GET\<.+\>', input) or re.match('BOUNCE\<.+\>', input) or input == 'EXIT' or re.match('EXIT\<.+\>', input):
return True
return False
def receiveAll(socket):
BUFF_SIZE = 4096 # 4 KiB
data = ""
while True:
part = socket.recv(BUFF_SIZE)
data += part
if len(part) < BUFF_SIZE:
# either 0 or end of data
break
return data
# create a client socket object
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# get local machine name
host = socket.gethostname()
# port number
port = 20000
# connection to hostname on the port.
s.connect((host, port))
while True:
request = raw_input()
if isValidRequest(request):
if request == 'EXIT' or re.match('EXIT\<.+\>', request):
s.send(request)
break
else:
s.send(request)
print "after send"
content = receiveAll(s)
print content
else:
print "Invalid request, please enter it again!"
# close client connection
s.close()
I run a test for request the same txt file-"MACD.txt" from server twice. The input in the console is "GET".The print message in the console for client:
*GET<MACD.txt>*
after send
MACD, short for moving average convergence/divergence, is a trading indicator used in technical analysis of stock prices, created by Gerald Appel in the late 1970s.[1] It is supposed to reveal changes in the strength, direction, momentum, and duration of a trend in a stock's price.
*GET<MACD.txt>*
socket.error: [Errno 10053] An established connection was aborted by the software in your host machine
after send
The print message in the server part. And you can see server only print message for the first request:
Got a connection from ('192.168.126.1', 60567)
('Server received', "u'GET<MACD.txt>'")
MACD, short for moving average convergence/divergence, is a trading indicator used in technical analysis of stock prices, created by Gerald Appel in the late 1970s.[1] It is supposed to reveal changes in the strength, direction, momentum, and duration of a trend in a stock's price.
I am confused by what I saw since I search the same problem in Stackoverflow and none of them match my case. I also read the document for python socket but still got nothing

Python - Socket Communication, multiple messages

I'm stuck on this socket communication, I've looked everywhere but I haven't found an answer yet.
THE PROBLEM: I can only send 1 message from the client before it either gives me an error or ends the script.
I need to be able to send multiple messages to the server.
The server side (shown below) should be fine:
# Echo server program
import socket
import time
import os
#-----------------------------------------------------------------------------------------------------------------------
today = time.strftime('%Y.%m.%d')
logFileName = "log - " + today + ".txt"
HOST = '10.0.0.16'
PORT = 8080 # Reserve a port for your service
BUFFER_SIZE = 1024
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # Create a socket object
s.bind((HOST, PORT)) # Bind to the port
def print_write(text):
log.write(time.strftime("%H:%M:%S") + " | " + text)
log.write("\n")
print text
#-----------------------------------------------------------------------------------------------------------------------
if os.path.isfile(logFileName) is True:
log = open(logFileName, 'a+')
print_write("[SERVER] Log for " + today + " already exists.")
print_write("[SERVER] Starting comms")
else:
print "[SERVER] Log doesn't exist"
log = open(logFileName, 'a+') # Create file -> log - %date%.txt
print_write("[SERVER] Log created")
while True:
s.listen(1)
conn, addr = s.accept()
data = conn.recv(BUFFER_SIZE)
if data == "Comms Shutdown":
print_write("------ REMOTE SHUTDOWN ------")
conn.close()
raise SystemExit
else:
print_write("[COMMS] " + str(addr) + " says: " + data)
log.close()
Sorry if it's very messy and confusing but i don't have much time to finish this project, if you have any question just ask.
For the client side I don't have much but here, I'll give you this:
import socket
HOST = '10.0.0.16' # The remote host
PORT = 8080 # The same port as used by the server
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((HOST, PORT))
while True:
msg = raw_input()
s.sendall(msg)
print msg
I know it doesn't work, it's just to give you an idea of what I need.
Thank you in advance.
The problem is, that you only read the first message from each open connection before moving on to the next. The accept() methods waits for a new connection and gives you the information needed when a new one comes in. the recv() method on the other hand, receives data from a existing connection and waits if there is none. If you want to receive multiple messages from a single client, you can just wait for the first connection and then wait for data with recv(). This could look like this:
s.listen(1)
conn, addr = s.accept()
while True:
data = conn.recv(BUFFER_SIZE)
if data == "Comms Shutdown":
print_write("------ REMOTE SHUTDOWN ------")
conn.close()
raise SystemExit
else:
print_write("[COMMS] " + str(addr) + " says: " + data)
If you want to be able to also manage multiple clients, you will have to create a thread for each one from a while loop waiting for new connections. This is a bit more complicated:
def client_handler(conn):
while True:
data = conn.recv(BUFFER_SIZE)
if data == "Comms Shutdown":
print_write("------ REMOTE SHUTDOWN ------")
conn.close()
raise SystemExit
# this will kill the server (remove the line above if you don't want that)
else:
print_write("[COMMS] " + str(addr) + " says: " + data)
while True:
s.listen(1)
conn, addr = s.accept()
recv_thread = threading.Thread(target=client_handler, args=(conn, ))
recv_thread.start()
All this code is untested. Be aware, that I omitted the logging part and the socket creation part as well as all imports.

Username/handle system using Python - TCP/IP chat client

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.

Python socket.recv exception

I'm working on a very simple python socket server. I use non-blocking sockets. The server and client are running on windows 7 x64 with python 2.7.3. Here is the code where I receive data from the client :
def listenToSockets(self):
while True:
changed_sockets = self.currentSockets
ready_to_read, ready_to_write, in_error = select.select(changed_sockets,[],[])
for s in ready_to_read:
# if its the server master socket someone is connecting
if s == self.socket:
(client_socket, address) = s.accept()
print "putting " + address[0] + " onto connections\n";
client_socket.setblocking(0)
self.currentSockets.append(client_socket)
print "current client count : " + str(len(self.currentSockets) - 1)
else:
data = ''
try:
while True:
part = s.recv(4096)
if part != '':
data = data + part
elif part == '':
break
except socket.error, (value,message):
print 'socket.error - ' + message
if data != '':
print "server received "+data
else:
print "Disconnected "+str(s.getsockname())
self.currentSockets.remove(s)
s.close()
And here is the client sending some data over and over again :
#client example
import socket
import time
client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client_socket.connect(('192.168.0.41', 9999))
while 1:
client_socket.send("test")
time.sleep(2)
I see the server receiving the message "test" over and over again. But before it prints out what it received I get the following error message.
socket.error - A non-blocking socket operation could not be completed immediately.
Obviously an exception is thrown at part = s.recv(4096) but why?
That's precisely what a nonblocking socket is supposed to do.
Read the available data, if any
If nothing is available, raise an error rather than blocking
So you're getting an exception every time you try to receive and there's no data available.

Categories

Resources