Server connected, but no response TCP socket programming - python

I'm implementing a circular distributed hash table, each peer knows its immediate successor and set up TCP connection with its successor, like, 1->3->4->5->8->1.
User will input a 4-digit number, and we proceed it into a certain value using a hash function written by us. For example, user inputs 3456, corresponding hash value is 128. Peer 3 get the input from user, and pass the hash value to its successor(4) asking if he is greater than hash value. If not, the successor will pass the hash to its successor(5). Repeat this until it find the right peer. (Here, since 8 < 128, we say peer 1 is the one we want)
Now, we know peer 1 is the peer we want. Then we let peer 1 make a TCP connection with the requesting peer 3, and send 3 "FIND1,3456,3", when peer 3 get this message, it should print out "peer 1 has the value".
The problem I met is, after I find peer 1 is the one I want, my peer 1 client sets up TCP connection with peer 3 server (peer 1 client said the connection is set up), but peer 3 doesn't get any message from peer 1, what's wrong with it?
How should I fix it?
Thanks for your patience to read these, feel free to ask if there is anything ambiguous :)
#!/usr/bin/python2.7
import sys
import socket
import time
import threading
import re
from collections import defaultdict
successor = defaultdict(dict)
peer = int(sys.argv[1])
successor[1] = int(sys.argv[2])
successor[2] = int(sys.argv[3])
serverName = 'localhost'
peerPort = 50000 + int(peer)
address = (serverName,peerPort)
#-------------proceed input string---------------------------
def getFileNum(name):
fileValid = re.match('^request ([0-9]{4})$',name)
if fileValid is None:
print 'invalid file!'
return
else:
hashName = fileValid.group(1)
return hashName
#----------------get request input--------------------------------
def getRequestInput(clientSocketTCP):
while flag == 0:
fileName = raw_input()
hashname = getFileNum(fileName)
if hashname is not None:
hashname = re.sub('^(0)*','',hashname)
hashnum = int(hashname) % 256
info = 'FILE_REQUEST'+str(hashname) + ','+ str(hashnum) + ','+ str(peer) + ',1'
clientSocketTCP.send(info)
print 'File request message for '+ str(hashname) + ' has been sent to my successor.'
clientSocketTCP.close()
#-------------------send file to successor---------------------------
def sendRequestToS(clientSocketTCP):
global important
while flag == 0:
if important:
an = re.match('^FILE_REQUEST([0-9]{4}),',important)
if an:
hashname = an.group(1)
clientSocketTCP.send(important)
print 'File request message for '+ str(hashname) + ' has been sent to my successor.'
important = ''
clientSocketTCP.close()
#-----------------------find file-------------------------------------
def findF():
global flag
global important
while flag == 0:
if re.match('^FIND',important):
obj = re.match('^FIND[0-9]{1,3},([0-9]{4}),([0-9]{1,3})',important)
n = int(obj.group(2))
info = important
ff = threading.Thread(target=clientTCPTemp,args=(n,info))
ff.start()
ff.join()
important = ''
#--------------------set up client temporary---------------------------
def clientTCPTemp(n,info):
global flag
clientConn = False
clientSocketTCP = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
serverPortTCP = 50000 + n
print serverPortTCP
while not clientConn:
try:
clientSocketTCP.connect((serverName,serverPortTCP))
clientConn = True
print "Now client connection works!!!!!"
except:
print "fail"
clientSocketTCP.send(info)
print info
print 'A response message, destined for peer '+ str(n) +', has been sent.'
clientSocketTCP.close()
#--------------------TCP server---------------------------------------
def serverTCP():
global flag
global serverSetUp
global important
serverSocketTCP = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
serverConn = False
while not serverConn:
try:
serverSocketTCP.bind((serverName,peerPort))
serverConn = True
serverSocketTCP.listen(2)
serverSetUp = 0
print 'The server is ready to receive'
except:
pass
while flag == 0:
connectionSocket, addr = serverSocketTCP.accept()
print 'connect by'+ str(addr)
threeinfo = connectionSocket.recv(1024)
print threeinfo
if re.match('^FILE_REQUEST',threeinfo):
obj = re.match('^FILE_REQUEST([0-9]{4}),([0-9]{1,3}),([0-9]{1,3}),([01])$',threeinfo)
if obj is not None:
filename = obj.group(1)
hashn = int(obj.group(2))
peerID = int(obj.group(3))
endCircle = int(obj.group(4))
if peer < hashn and endCircle:
print 'File ' +filename +' is not stored here. '
important = threeinfo
if peer > successor[1]:
important = re.sub('1$','0',threeinfo)
else:
print 'File '+ filename+' is here.'
important = 'FIND'+str(peer)+','+ filename +','+ str(peerID)
elif re.match('^FIND',threeinfo):
dest = re.match('^FIND([0-9]{1,3}),([0-9]{4})','',threeinfo)
fromP = dest.group(1)
fileP = dest.group(2)
print 'Received a response message from peer '+fromP+', which has the file '+fileP
connectionSocket.send('i receive from you------------------------')
print sen
connectionSocket.send('can you hear me?')
connectionSocket.close()
#--------------------TCP client----------------------------------------
def clientTCP(n):
global flag
global serverSetUp
global important
clientConn = False
# while serverSetUp == 1:
# pass
clientSocketTCP = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
serverPortTCP = 50000 + n
while not clientConn:
try:
clientSocketTCP.connect((serverName,serverPortTCP))
clientConn = True
print "Now client connection works!!!!!"
except:
pass
try:
rt = threading.Thread(target=getRequestInput,args=(clientSocketTCP,))
sr = threading.Thread(target=sendRequestToS,args=(clientSocketTCP,))
ff = threading.Thread(target=findF,args=())
rt.start()
sr.start()
ff.start()
except:
print 'thread failed'
sen = raw_input()
clientSocketTCP.send(sen)
m = clientSocketTCP.recv(1024)
print m
clientSocketTCP.close()
#----------------start thread---------------------------------
#------adapt from https://www.tutorialspoint.com/python/python_multithreading.html --------
flag = 0
serverSetUp = 1
important = ''
findFile = False
try:
serTCP = threading.Thread(target=serverTCP,args=())
cliTCP = threading.Thread(target=clientTCP,args=(successor[1],))
serTCP.start()
cliTCP.start()
except:
print "thread can not be set up"
while flag == 0:
try:
pass
except KeyboardInterrupt:
flag = 1

Related

Python client socket not receiving data from TCP server

I'm trying to build a fake money transfer program with sockets in python. Everything is working perfectly except the "name" and "amount" transfer from the server to the client. When someone clicks receive on the client interface, the server is supposed to send the client the name of the person who sent the money and the amount. The problem is that the client is not receiving the data sent from the server. When you click the "receive" button, the interface just freezes then crashes. From the debugging I've done, I'm pretty sure the server is sending the name and amount, but the client is not receiving it. I honestly have no idea why it's not working. Everything I did should work like it has numerous other times throughout the program. This one has got me stumped.
Any help would be great. Thanks! 😁
[CODE]
Server.py:
import socket
import threading
HOST = '192.168.1.6'
PORT = 9090
def client_fun(client, addr):
global transfers
print(f"{addr} just connected!")
connected = True
while connected:
msg = client.recv(1024).decode('utf-8')
if msg == "RECEIVE_CHECK":
usrn = client.recv(1024).decode('utf-8')
transfers_ = open("transfers.txt", "r")
transfers = str(transfers_.readlines())
transfers = transfers.split("+")
transfers[0] = transfers[0].replace("[", "")
transfers[0] = transfers[0].replace("'", "")
transfers.pop()
names = []
for tran in transfers:
tran_ = tran.split("-")
i = 0
while i <= len(tran):
names.append(tran_[2])
i += 1
if usrn in names:
client.send("OK".encode('utf-8'))
else:
client.send("NO".encode('utf-8'))
if usrn in names:
for tran in transfers:
tran_ = tran.split("-")
if usrn == tran_[2]:
name = str(tran_[0])
amount = str(tran_[1])
client.send(name.encode('utf-8'))
client.send(amount.encode('utf-8'))
account_file = usrn + "_" + "account.txt"
account_r = open(account_file, "r")
account_r = str(account_r.readlines())
account_r = account_r.replace(']', '')
account_r = account_r.replace('[', '')
account_r = account_r.replace("'", "")
try:
account_r = int(account_r)
except:
print("Can't Convert Str to Int!")
break
new_amount = int(tran_[1]) + account_r
account_w = open(account_file, "w")
account_w.write(str(new_amount))
account_w.close()
tran = tran + "+"
transFers_ = open("transfers.txt", "r")
transFers = str(transFers_.readlines())
transFers_.close()
transFers = transFers.replace(']', '')
transFers = transFers.replace('[', '')
transFers = transFers.replace("'", "")
transFers = transFers.replace(tran, '')
transFers_ = open("transfers.txt", 'w+')
transFers_.write(transFers)
transFers_.close()
print("Excepted!")
else:
print("Nothing Here!")
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind((HOST, PORT))
server.listen()
print("Server is listening!")
while True:
c_socket, address = server.accept()
thread = threading.Thread(target=client_fun, args=(c_socket, address))
thread.start()
Client.py:
import socket
HOST = '192.168.1.6'
PORT = 9090
socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
def receive(usrn):
socket.send("RECEIVE_CHECK".encode('utf-8'))
socket.send(usrn.encode('utf-8'))
c = socket.recv(1024).decode('utf-8')
if c == "OK":
try:
print("Trying to except....")
name = socket.recv(2000).decode('utf-8')
amount = socket.recv(2000).decode('utf-8')
print("Excepted!")
messagebox.showwarning("Continue?", f"{name} has sent you ${amount}", icon="question")
messagebox.showwarning("Info", f"${amount} has just been transferred to your account!", icon="info")
menu(usrn)
except:
print("Error!")
else:
print("Nothing Today!")

python Port scanner that reads ports from . txt

My issue is that I have a ports.txt file in it has 4 port numbers. I wish for this program to scan all port numbers specified within the txt file. currently It will only scan the first port number listed in the txt file against the 40 odd IP addresses. I hope my formatting is correct and my detail is enough. ty
import socket
import os
import sys
from datetime import datetime
import win32evtlogutil
import win32evtlog
def main():
### call step 1 function
ipList = network_addr()
# call step 2 function
portList = read_ports()
print(portList)
#call step 3 function
for ip in ipList:
for port in portList:
scan_ports(ip,port)
# call step 4 function
report_to_EventViewer(ipList[0:10], 2) # warning
#report_to_EventViewer(ipList, 1) # error
# processing inputs
# Step 1: process input 1 (subnet or network address):
def network_addr():
while True:
ip_list = []
subnet_Addr = input('Enter a Class-C Network Address or subnet with format (x.x.x): ')
subnet = subnet_Addr.split('.') # subnet is a list of 3 items (octets)
try:
if (len(subnet)==3 and 192<=int(subnet[0])<=223 and 0<=int(subnet[1])<=255 and 0<=int(subnet[2])<=255):
#return subnet_Addr
print('valid subnet: ',subnet_Addr)
for ip in range(11,40,2):
ip_temp = subnet_Addr + '.' + str(ip)
ip_list.append(ip_temp)
return ip_list
else:
value = 'wrong subnet entered'
print(value)
except ValueError:
print('wrong subnet entered, octects must be digits')
# Step 2: process input 2 (read port numbers from ports.txt):
def read_ports():
with open("ports.txt", 'r') as file_path:
port_list = []
for port in file_path:
try:
if int(port) in port_list:
print(f'port: {port} already exists')
else:
port_list.append(int(port))
except:
print(f'the port number: {port} is not a valid integer')
return port_list
else:
print('ports.txt is empty \n .... Exiting Port Scan App')
sys.exit()
# Step 3: scan ports
def scan_ports(ip,port):
# to get and format system time
dateTimeObj = datetime.now()
timeStamp = dateTimeObj.strftime("%d-%b-%Y (%H:%M:%S)")
try:
# open log file
with open("ip_port_log.txt","+r") as log:
# create client socket
socket.setdefaulttimeout(0.1)
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
result = sock.connect_ex((ip,port))
if result == 0:
data = "IP:" + ip + ":" + str(port) + " Open " + timeStamp
# write_to_console or display on screen
print(data)
# write in log file
log.write(data + "\n")
else:
data = "IP:" + ip + ":" + str(port) + " Closed/Filtered or host is offline " + timeStamp
# write_to_console or display on screen
print(data)
# write in log file
log.write(data + "\n")
# close the client socket
sock.close()
except socket.error:
print("Can't connect to IP: ", ip)
sys.exit()
except KeyboardInterrupt:
print("User pressed Ctrl+c")
sys.exit()
# Step 4: Report to Event Viewer
# output 3
def report_to_EventViewer(mylist, eventtype):
IP_EVT_APP_NAME = " CheckIPPort - IP-Port Scan Application"
IP_EVT_ID = 7040 ##According to ???
IP_EVT_CATEG = 9876 ##According to ???
IP_EVT_TYPE = win32evtlog.EVENTLOG_WARNING_TYPE # WARNING=2
IP_EVT_ERR = win32evtlog.EVENTLOG_ERROR_TYPE # ERROR=1
IP_EVT_STRS = mylist
IP_EVT_DATA = b"Scan IP Address Event Data"
win32evtlogutil.ReportEvent(IP_EVT_APP_NAME, \
IP_EVT_ID, \
eventCategory=IP_EVT_CATEG, \
eventType=eventtype, \
strings=IP_EVT_STRS, \
data=IP_EVT_DATA)
main()
you issue is in your read_ports method, you return inside the loop so it will ALWAYS only read the first one. Rewrite the method to something like:
def read_ports():
with open("ports.txt", 'r') as file_path:
port_list = []
for port in file_path:
try:
if int(port) in port_list:
print(f'port: {port} already exists')
else:
port_list.append(int(port))
except:
print(f'the port number: {port} is not a valid integer')
if not len(port_list):
print('ports.txt is empty \n .... Exiting Port Scan App')
sys.exit()
return port_list

Sending and receiving package in python

This is a console chat app on a TCP socket server. The client will send the request/message to the server and the server will distribute the message to the target user or provide requested information.I am currently running into a problem regarding the recv package on the server side. I received the package and was able to print it out. However the system still give me a syntax error for some reason.
Thanks.
This is my client:
import socket
import select
import errno
import sys, struct
import pickle
HEADER_LENGTH = 1024
IP = "127.0.0.1"
PORT = 9669
def send_login_request(username):
package = [1]
length = len(username)
if length > 1019:
print ("Error: Username too long")
sys.exit()
package += struct.pack("I", length)
package += username
return package
def send_message(recv_id, message):
package = [2]
length = len(message)
if length > 1015:
print('message too long')
sys.exit()
package += recv_id
package += struct.pack('I', length)
package += message
return package
def send_con_request(conv_id):
package = [3]
length = len(id)
if length > 1015:
print('id too long')
sys.exit()
package += struct.pack("I", length)
package += conv_id
return package
# Create a socket
client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# Connect to a given ip and port
client_socket.connect((IP, PORT))
client_socket.setblocking(False)
my_username = input("Username: ")
request = send_login_request(my_username)
user_request = str(request)
client_socket.send(user_request.encode())
username_conf = client_socket.recv(HEADER_LENGTH).decode()
if username_conf == "Welcome to the server":
con_id = input("Please enter conversation's id, if don't have one, please enter no ")
if con_id == 'no':
con_request = send_con_request(con_id)
con_request = str(con_request)
client_socket.send(con_request.encode())
else:
con_request = send_con_request(con_id)
con_request = str(con_request)
client_socket.send(con_request.encode())
conversation = client_socket.recv(HEADER_LENGTH).decode()
recv_id = input("Please enter receiver's id")
while True:
# Wait for user to input a message
message = input(f'{my_username} > ').encode()
# If message is not empty - send it
if message:
send_message = send_message(recv_id,message)
client_socket.send(bytes(send_message))
try:
while True:
message_receiver = client_socket.recv(HEADER_LENGTH).decode()
x = message_receiver.split('|')
print(x)
username = x[0]
message = x[1]
# Print message
print(f'{username} > {message}')
except IOError as e:
if e.errno != errno.EAGAIN and e.errno != errno.EWOULDBLOCK:
print('Reading error: {}'.format(str(e)))
sys.exit()
# We just did not receive anything
continue
except Exception as e:
# Any other exception - something happened, exit
print('Reading error: {}'.format(str(e)))
sys.exit()
This is my server:
import socket
import select
import struct
import sys
import pickle
HEADER_LENGTH = 1024
conversation ={}
users = [
{
'username': 'user1',
'user_id': 1
},
{
'username': 'user2',
'user_id': 2
},
{
'username': 'user3',
'user_id': 3
},
{
'username': 'user4',
'user_id': 4
},
{
'username': 'user5',
'user_id': 5
}
]
def login(username):
for user in users:
if user['username'] == username:
return user
else:
return False
IP = "127.0.0.1"
PORT = 9669
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
server_socket.bind((IP, PORT))
server_socket.listen()
# List of sockets for select.select()
sockets_list = [server_socket]
# List of connected clients - socket as a key, user header and name as data
clients_socket = {}
sessions = {
(1,2) : '1.txt',
(3,4) : '2.txt'
}
def getRecvSocket(user_id):
try:
return sessions[user_id]
except:
return None
def sendErrorMes(socketid, mes):
package = [9]
length = len(mes)
if length > 1019:
length = 1019
package += struct.pack("I", length)
package += mes
print(f'Listening for connections on {IP}:{PORT}...')
# Handles message receiving
def receive_message(client_socket):
try:
receive_message = client_socket.recv(HEADER_LENGTH)
return receive_message
except:
return False
while True:
read_sockets, _, exception_sockets = select.select(sockets_list, [], sockets_list)
# Iterate over notified sockets
for notified_socket in read_sockets:
# If notified socket is a server socket - new connection, accept it
if notified_socket == server_socket:
client_socket, client_address = server_socket.accept()
sockets_list.append(client_socket)
else:
# Receive message
package = receive_message(notified_socket)
print(package)
package_recv = eval(package.decode())
print(package_recv)
print(type(package_recv))
package_type = package_recv[0]
if package_type == 1:
size = struct.unpack("I", package[1:5])
if size[0] > 1019:
continue
username = package[5:5+size[0]]
username = username.decode()
# username = package_recv[1]
user = login(username)
if user == False:
notified_socket.send("no user found".encode())
else:
sessions[user["user_id"]] = notified_socket
notified_socket.send(("Welcome to the server").encode())
elif package_type == 2:
recv_id = struct.unpack("I", package[1:5])
size = struct.unpack("I", package[5:9])
if size[0] > 1015:
continue
# recv_id = package_recv[1]
if getRecvSocket(recv_id) == None:
sendErrorMes(notified_socket, "User is offline")
else:
message = package[9:9+size[0]]
# message = package_recv[2]
for socket in sessions.values():
if socket == notified_socket:
user = sessions[notified_socket]
# print(f'Received message from {user}, {message}')
# fIterate over connected clients and broadcast message
for client_socket in clients_socket:
# if clients[client_socket] == receive_user and client_socket != notified_socket:
# But don't sent it to sender
if client_socket != notified_socket and clients_socket[client_socket] == recv_id:
# Send user and message (both with their headers)
# We are reusing here message header sent by sender, and saved username header send by user when he connected
a = sessions[notified_socket]
b = recv_id
with open(f"{conversation[a,b]}.txt", "w"):
f.write(user + message)
client_socket.send((user + "|" + message).encode())
if message is False:
# print('Closed connection from: {}'.format(user))
# Remove from list for socket.socket()
sockets_list.remove(notified_socket)
# Remove from our list of users
del clients_socket[notified_socket]
continue
elif package_type == 3:
size = struct.unpack("I", package[1:5])
if size[0] > 1019:
continue
convo_id = package[5:5+size[0]]
convo_id = convo_id.decode()
# convo_id = package_recv[2]
if convo_id in conversation:
with open(conversation[convo_id], 'rb') as file_to_send:
for data in file_to_send:
notified_socket.sendall(data)
print('send successful')
else:
f = open(f"{len(conversation)+1}.txt", "w+")
This is the error in the server side which I am having a problem to locate and solve:
Listening for connections on 127.0.0.1:9669...
b"[1, 5, 0, 0, 0, 'u', 's', 'e', 'r', '1']"
[1, 5, 0, 0, 0, 'u', 's', 'e', 'r', '1']
<class 'list'>
b''
Traceback (most recent call last):
File "c:/Users/Duong Dang/Desktop/bai 2.3/server.py", line 134, in <module>
package_recv = eval(package.decode())
File "<string>", line 0
^
SyntaxError: unexpected EOF while parsing
The sending code doesn't make a lot of sense. You're creating a python list which is a most strange way to implement a protocol. You're then taking python's string representation of that list and sending it to the server. You're not doing anything on the server side to ensure that you got the entire message. Then you're using eval to interpret the string you created on the client. That is a very dangerous practice, as your peer can essentially instruct your python interpreter to do literally anything.
Also, your send_con_request is calling len(id) which won't work at all because id is a python built-in that doesn't supply a __len__ method. I assume that was supposed to be len(conv_id)?
Anyway, you should rework your protocol. Use the struct tools to create the correct binary string you want. There are tons of possible ways to structure this but here's one. On the client side, create a fixed-length header that identifies which request type you're sending and the length of the remaining "payload" bytes. You'll convert your string (username or whatever) into bytes first with str.encode.
import struct
# ProtoHeader encodes a 16 bit request identifer, plus a 32 bit payload
# length. A protocol data unit consists of this 6-byte header followed by
# payload bytes (which will vary according to the request)
ProtoHeader = struct.Struct("!HI")
LoginRequest = 1
SomeOtherRequest = 2
...
def format_login_request(username):
""" Create a protocol block containing a user login request.
Return the byte string containing the encoded request """
username_bytes = username.encode()
proto_block = ProtoHeader.pack(LoginRequest, len(username_bytes)) + username_bytes
return proto_block
...
conn.sendall(format_login_request(username))
On the server side, you will first receive the fixed-length header (which tells you what the request type was and how many other payload bytes are present). Then receive those remaining bytes ensuring that you get exactly that many. socket.recv does not guarantee that you will receive exactly the number of bytes sent in any particular send from the peer. It does guarantee that you will get them in the right order so you must keep receiving until you got exactly the number you expected. That's why it's important to have fixed length byte strings as a header and to encode the number of bytes expected in variable length payloads.
The server would look something like this:
import struct
ProtoHeader = struct.Struct("!HI")
LoginRequest = 1
def receive_bytes(conn, count):
""" General purpose receiver:
Receive exactly #count bytes from #conn """
buf = b''
remaining = count
while remaining > 0:
# Receive part or all of data
tbuf = conn.recv(remaining)
tbuf_len = len(tbuf)
if tbuf_len == 0:
# Really you probably want to return 0 here if buf is empty and
# allow the higher-level routine to determine if the EOF is at
# a proper message boundary in which case, you silently close the
# connection. You would normally only raise an exception if you
# EOF in the *middle* of a message.
raise RuntimeError("end of file")
buf += tbuf
remaining -= tbuf_len
return buf
def receive_proto_block(conn):
""" Receive the next protocol block from #conn. Return a tuple of
request_type (integer) and payload (byte string) """
proto_header = receive_bytes(conn, ProtoHeader.size)
request_type, payload_length = ProtoHeader.unpack(proto_header)
payload = receive_bytes(conn, payload_length)
return request_type, payload
...
request_type, payload = receive_proto_block(conn)
if request_type == LoginRequest:
username = payload.decode()

Receive more than one message on more than one port Echo Server python

I am writing a echo server and client in Python, that implements a simple number guessing game. I know how to multiplex using select, that's fine. The other server I wrote achieves this. But now I am writing a new server (which is fairly similar), however it accepts connections from two ports rather than one, one port for player client, and one for admin which I will use eventually for the who command, returning all connected players.
My problem is, that after sending the initial greetings message, the clients receive feedback from the server on the first send, recv. But after that I cannot send any more messages to server (nothing gets sent from the clients), I have been searching and playing around for hours, to no avail. Any help would be appreciated. Thanks!
# MULTIPLEX SERVER
import socket, select, time, random, ssl, sys, os
# VARS
EXP = 1
HOST = '127.0.0.1'
PORT_P = 4000
PORT_A = 4001
BUFFSZ = 1024
BKLOG = 5
GREETS = 'Greetings'
INPUTS = []
OUTPUTS = []
CLIENT_ADDRS = {}
CLIENT_ANS = {}
CLIENTS = ""
_adm_rtnMSG = 'Admin_Greetings'
# Function to determine how far the player is
# from the chosen random number
def Within(value, target):
diff = abs(target - value)
if diff > 3:
return 'Not even close, youth!'
else:
return 'Ooh, not to far: ' + str(diff) + ' away, keep trying...'
# END_FUNCTION
print('Server up and running...\n')
try:
for p in PORT_P, PORT_A:
INPUTS.append(socket.socket(socket.AF_INET, socket.SOCK_STREAM))
INPUTS[-1].setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
INPUTS[-1].bind((HOST, p))
INPUTS[-1].listen(BKLOG)
except socket.error(value, message):
if INPUTS[-1]:
INPUTS[-1].close()
INPUTS = INPUTS[:-1]
print('Failure to open socket: ' + message)
sys.exit(1)
while True:
READ_IO, WRITE_IO, ERROR = select.select(INPUTS, OUTPUTS, INPUTS)
for r in READ_IO:
for p in INPUTS:
if r is p:
(acpt_sock, addr) = p.accept()
print('Connection established with ', acpt_sock.getsockname())
CLIENT_ADDRS[acpt_sock] = addr
CLIENT_ANS[acpt_sock] = random.randrange(1, 20)
else:
data = acpt_sock.recv(BUFFSZ).decode()
acpt_sock.setblocking(0)
if data:
if 'Hello' in data:
print(CLIENT_ADDRS[acpt_sock], ' random number is: ', CLIENT_ANS[acpt_sock])
acpt_sock.send(b'Greetings\nGuess a random number between 1 & 20')
# drop elif here for admin cmd
elif 'Hi' in data:
acpt_sock.send(_adm_rtnMSG.encode())
else:
if int(data) == CLIENT_ANS[acpt_sock]:
acpt_sock.send(b'That was correct, Well done!')
else:
acpt_sock.send(str(Within(int(data), CLIENT_ANS[acpt_sock])).encode())
else:
print('Closing Connection # ', addr)
INPUTS.remove(acpt_sock)
acpt_sock.close()
del CLIENT_ADDRS[acpt_sock]
# PLAYER CLIENT
import socket
import re
# INIT VARS
HOST = '127.0.0.1'
PORT = 4000
INITSTR = 'Hello'
BUFF = 1024
# Set up socket
sender = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sender.connect((HOST, PORT))
sender.send(bytes((INITSTR), "ascii"))
print("Kirby Prompt FTW!\nConnected to Server via", HOST, "::", PORT, '\n')
rtnMSG = sender.recv(BUFF).decode()
print(rtnMSG)
# Simple loop to keep client alive
# to send and receive data from the server
while 'correct' not in rtnMSG:
_guess = input("(>',')> ")
sender.send(bytes((_guess), "ascii"))
rtnMSG = sender.recv(BUFF).decode()
print(rtnMSG)
sender.close()
# ADMIN CLIENT
import socket
import re
import ssl
# INIT VARS
HOST = '127.0.0.1'
PORT = 4001
INITSTR = 'Hi'
BUFF = 1024
# Set up socket
adm_sender = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
adm_sender.connect((HOST, PORT))
adm_sender.send(bytes((INITSTR), "ascii"))
print("Connected to Server as Admin via", HOST, "::", PORT, '\n')
rtnMSG = adm_sender.recv(BUFF).decode()
print(rtnMSG)
while True:
cmd = input('$ ')
adm_sender.send(bytes((cmd), "ascii"))
rtnMSG = adm_sender.recv(BUFF).decode()
print(rtnMSG)
adm_sender.close()

python Client hangs when no data to receive from server and hangs in that thread w/o letting client send

I am trying to figure out how to get my client to send and receive data 'simultaneously' and am using threads. My problem is that, depending on the way I set it up, the way here it waits for data from the server in the recieveFromServer function which is in its own thread and cannot stop it when nothing will be sent. The other way it just waits for user input, and will send to the server and then I'd call the function recieveFromServer after the client sends a message to the server which doesn't allow for fluent communication, but cannot get it to alternate automatically. How do I release the thread when the client has nothing to be sent, or there is no more to be received from the server.
It would get to long if I tried to explain everything I have tried. :)
Thanks.
The client:
from socket import *
from threading import *
import thread
import time
from struct import pack,unpack
from networklingo import *
#from exception import *
HOST = '192.168.0.105'
PORT = 21567
BUFFSIZE = 1024
ADDR = (HOST,PORT)
lock = thread.allocate_lock()
class TronClient:
def __init__(self,control=None):
self.tcpSock = socket(AF_INET,SOCK_STREAM)
#self.tcpSock.settimeout(.2)
self.recvBuff = []
def connect(self):
self.tcpSock.connect(ADDR)
self.clientUID = self.tcpSock.recv(BUFFSIZE)
print 'My clientUID is ', self.clientUID
t = Thread(target = self.receiveFromSrv())
t.setDaemon(1)
t.start()
print 'going to main loop'
self.mainLoop()
#t = Thread(target = self.mainLoop())
#t.setName('mainLoop')
#t.setDaemon(1)
#t.start()
def receiveFromSrv(self):
RECIEVING = 1
while RECIEVING:
#print 'Attempting to retrieve more data'
#lock.acquire()
#print 'Lock Aquired in recieveFromSrv'
#try:
data = self.tcpSock.recv(BUFFSIZE)
#except socket.timeout,e:
#print 'Error recieving data, ',e
#continue
#print data
if not data: continue
header = data[:6]
msgType,msgLength,clientID = unpack("hhh",header)
print msgType
print msgLength
print clientID,'\n'
msg = data[6:]
while len(msg) < msgLength:
data = self.tcpSock.recv(BUFFSIZE)
dataLen = len(data)
if dataLen <= msgLength:
msg += data
else:
remLen = msgLength-len(data) #we just need to retrieve first bit of data to complete msg
msg += data[:remLen]
self.recvBuff.append(data[remLen:])
print msg
#else:
#lock.release()
# print 'lock release in receiveFromSrv'
#time.sleep(2)
#RECIEVING = 0
def disconnect(self,data=''):
self.send(DISCONNECT_REQUEST,data)
#self.tcpSock.close()
def send(self,msgType,msg):
header = pack("hhh",msgType,len(msg),self.clientUID)
msg = header+msg
self.tcpSock.send(msg)
def mainLoop(self):
while 1:
try:
#lock.acquire()
#print 'lock aquired in mainLoop'
data = raw_input('> ')
except EOFError: # enter key hit without any data (blank line) so ignore and continue
continue
#if not data or data == '': # no valid data so just continue
# continue
if data=='exit': # client wants to disconnect, so send request to server
self.disconnect()
break
else:
self.send(TRON_CHAT,data)
#lock.release()
#print 'lock released in main loop'
#self.recieveFromSrv()
#data = self.tcpSock.recv(BUFFSIZE)
#t = Thread(target = self.receiveFromSrv())
#t.setDaemon(1)
#t.start()
if __name__ == "__main__":
cli = TronClient()
cli.connect()
#t = Thread(target = cli.connect())
#t.setName('connect')
#t.setDaemon(1)
#t.start()
The server (uses a lock when incrementing or decrementing number of clients):
from socket import *
from threading import *
import thread
from controller import *
from networklingo import *
from struct import pack,unpack
HOST = ''
PORT = 21567
BUFSIZE = 1024
ADDR = (HOST,PORT)
nclntlock = thread.allocate_lock()
class TronServer:
def __init__(self,maxConnect=4,control=None):
self.servSock = socket(AF_INET,SOCK_STREAM)
# ensure that you can restart server quickly when it terminates
self.servSock.setsockopt(SOL_SOCKET,SO_REUSEADDR,1)
self.servSock.bind(ADDR)
self.servSock.listen(maxConnect)
# keep track of number of connected clients
self.clientsConnected = 0
# give each client a unique identfier for this run of server
self.clientUID = 0
# list of all clients to cycle through for sending
self.allClients = {}
# keep track of threads
self.cliThreads = {}
#reference back to controller
self.controller = control
self.recvBuff = []
def removeClient(self,clientID,addr):
if clientID in self.allClients.keys():
self.allClients[clientID].close()
print "Disconnected from", addr
nclntlock.acquire()
self.clientsConnected -= 1
nclntlock.release()
del self.allClients[clientID]
else:
print 'ClientID is not valid'
def recieve(self,clientsock,addr):
RECIEVING = 1
# loop serving the new client
while RECIEVING: # while PLAYING???
try:
data = clientsock.recv(BUFSIZE)
except:
RECIEVING = 0
continue
# if not data: break #no data was recieved
if data != '':
print 'Recieved msg from client: ',data
header = data[:6]
msgType,msgLength,clientID = unpack("hhh",header)
print msgType
print msgLength
print clientID,'\n'
if msgType == DISCONNECT_REQUEST: #handle disconnect request
self.removeClient(clientID,addr)
else: #pass message type and message off to controller
msg = data[6:]
while len(msg) < msgLength:
data = self.tcpSock.recv(BUFSIZE)
dataLen = len(data)
if dataLen <= msgLength:
msg += data
else:
remLen = msgLength-len(data) #we just need to retrieve first bit of data to complete msg
msg += data[:remLen]
self.recvBuff.append(data[remLen:])
print msg
# echo back the same data you just recieved
#clientsock.sendall(data)
self.send(TRON_CHAT,msg,-1) #send to client 0
for k in self.allClients.keys():
if self.allClients[k] == clientsock:
self.removeClient(k,addr)
print 'deleted after hard exit from clientID ', k
#self.cliThreads[k].join()
#del self.cliThreads[k]
# then tell controller to delete player with k
break
def send(self,msgType,msg,clientID=-1):
header = pack("hhh",msgType,len(msg),clientID)
msg = header+msg
if clientID in self.allClients:
self.allClients[clientID].send(msg)
elif clientID==ALL_PLAYERS:
for k in self.allClients.keys():
self.allClients[k].send(msg)
def mainLoop(self):
global nclntlock
try:
while self.controller != None and self.controller.state == WAITING:
print 'awaiting connections'
clientsock, caddy = self.servSock.accept()
nclntlock.acquire()
self.clientsConnected += 1
nclntlock.release()
print 'Client ',self.clientUID,' connected from:',caddy
clientsock.setblocking(0)
clientsock.send(str(self.clientUID))
self.allClients[self.clientUID] = clientsock
t = Thread(target = self.recieve, args = [clientsock,caddy])
t.setName('recieve-' + str(self.clientUID))
self.cliThreads[self.clientUID] = t
self.clientUID += 1
# t.setDaemon(1)
t.start()
finally:
self.servSock.close()
if __name__ == "__main__":
serv = TronServer(control = LocalController(nPlayers = 3, fWidth = 70, fHeight = 10))
t = Thread(target = serv.mainLoop())
t.setName('mainLoop')
# t.setDaemon(1)
t.start()
I think you want to try and set the socket to non-blocking mode:
http://docs.python.org/library/socket.html#socket.socket.setblocking
Set blocking or non-blocking mode of
the socket: if flag is 0, the socket
is set to non-blocking, else to
blocking mode. Initially all sockets
are in blocking mode. In non-blocking
mode, if a recv() call doesn’t find
any data, or if a send() call can’t
immediately dispose of the data, a
error exception is raised; in blocking
mode, the calls block until they can
proceed. s.setblocking(0) is
equivalent to s.settimeout(0);
s.setblocking(1) is equivalent to
s.settimeout(None).
Also, instead of using raw sockets, have you considdered using the multiprocessing module. It is a higher-level abstraction for doing network IO. The section on Pipes & Queues is specific to sending and receiving data between a client/server.

Categories

Resources