I am new to python and trying to create a test bed where I have a TCP half open and TCP half close situations between a client and the server.
Server code:
def recv_end(the_socket):
End='SERVER WRONG MARKER'
total_data=[];data='';got_end=False
while True:
data=the_socket.recv(8192)
if not data: break
if End in data:
total_data.append(data[:data.find(End)])
got_end=True
break
total_data.append(data)
if len(total_data)>1:
#check if end_of_data was split
last_pair=total_data[-2]+total_data[-1]
if End in last_pair:
total_data[-2]=last_pair[:last_pair.find(End)]
total_data.pop()
got_end=True
break
return (got_end,''.join(total_data))
def basic_server(sock):
got=[]
got_end,data = recv_end(sock)
if not got_end:
sock.send('ERROR:no end!') #<--- not possible w/close()
else: sock.sendall(data*2)
sock.shutdown(1)
sock.close()
import socket
Port=4444
def start_server():
sock=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
sock.bind(('',Port))
sock.listen(5)
print 'started on',Port
while True:
newsock,address=sock.accept()
basic_server(newsock)
def send_data(data):
sock=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
sock.connect(('localhost',Port))
print 'connected'
sock.sendall(data+'CLIENT WRONG MARKER')
print 'sent',data
sock.shutdown(1)
print 'shutdown'
result=[]
while True:
got=sock.recv(2)
if not got: break
result.append(got)
sock.close()
return ''.join(result)
if __name__=='__main__':
start_server()
The client code :
import socket
def send_data(data):
sock=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
sock.connect(('localhost',Port))
print 'connected'
sock.sendall(data+'CLIENT WRONG MARKER')
print 'sent',data
sock.shutdown(1)
print 'shutdown'
result=[]
while True:
got=sock.recv(2)
if not got: break
result.append(got)
sock.close()
return ''.join(result)
def shut_serv_end():
data=('a1234','b1234','c1234','d1234','e1234')
for d in data:
print shut_srv.send_data(d)
I am trying to use the shutdown command that has three options: 0 = done receiving, 1 = done sending, 2 = both
In the code above focuses on 1. The code isn't working as expected. Meaning, I don't see half open connections when I do a packet capture. Can anyone please provide some tips or examples of how one to achieve it or what mistake am I doing?
Related
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 1 year ago.
Improve this question
I created a socket server to read the commands from a socket client. In client side, I send ABC and then DEF, in server side, each time I received ABC or DEF from client, the server will send back to client OK.
Server
import socket
import sys
host = socket.gethostname()
port = 12345
server_tcp = socket.socket()
server_tcp.bind((host, port))
server_tcp.listen(5)
while True:
c, addr = server_tcp.accept()
data = c.recv(1024)
print ('data received: %s') % data
if 'ABC' == data:
print ('sending back ok to the client')
texte = 'OK';
n=c.send(texte)
else:
print ('I did not get the right command ABC')
break
data = c.recv(1024)
print ('data received: %s') % data
if 'DEF' == data:
print ('sending back ok to the client')
texte = 'OK';
n=c.send(texte)
else:
print ('I did not get the right command DEF')
break
c.close()
Socket client:
import socket
import sys
host = socket.gethostname()
port = 12345
client_tcp = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
rc = client_tcp.connect((host, port))
except:
print('Server not found')
texte = 'ABC';
n=client_tcp.send(texte)
data=client_tcp.recv(1024);
print (data)
if 'OK' == data:
print('good')
else:
print('bad')
texte = 'DEF';
n=client_tcp.send(texte)
data=client_tcp.recv(1024);
print (data)
if 'OK' == data:
print('good')
else:
print('bad')
client_tcp.close() # Close the socket when done
When I set the command in client with order ABC - DEF I receive OK - OK in server. But with DEF - ABC, I just only received only one OK.
Best regards
I made some changes to your code to test it. The problem is that you are not sending the response that the client is waiting for. It happens when the wrong command arrives.
if your client is waiting for information YOUR SERVER MUST SENDS INFORMATION!... and it's the same for the other side (Server).
In the end, your problem is an issue of protocol. You must design what kind of message will be changed between different parts and be sure that those messages are sent and received
Server:
import socket
import sys
host = socket.gethostname()
port = 9966
server_tcp = socket.socket()
server_tcp.bind((host, port))
server_tcp.listen(5)
n = 0
while n < 2:
c, addr = server_tcp.accept()
inData = c.recv(1024)
data = inData.decode()
texte = '';
print ('data received: {0}'.format(data))
if 'ABC' == data:
print ('sending back ok to the client')
texte = 'OK';
else:
print ('I did not get the right command ABC')
texte = 'FAIL';
#break
print("Respose: {0}".format(texte))
#ALWASY SEND THE RESPONSE IF YOUR CLIENT WAITS FOR IT
c.sendall(texte.encode(encoding = 'UTF-8'))
inData = c.recv(1024)
data = inData.decode()
print ('data received: {0}'.format(data))
if 'DEF' == data:
print ('sending back ok to the client')
texte = 'OK';
#n=c.send(texte.encode(encoding = 'UTF-8'))
else:
print ('I did not get the right command DEF')
texte = 'FAIL';
#break
print("Respose: {0}".format(texte))
#ALWASY SEND THE RESPONSE IF YOUR CLIENT WAITS FOR IT
c.sendall(texte.encode(encoding = 'UTF-8'))
print ('Closing Socket Client')
c.close()
n += 1
Client:
import socket
import sys
host = socket.gethostname()
port = 9966
client_tcp = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
rc = client_tcp.connect((host, port))
except:
print('Server not found')
#texte = "ABC"
texte = "DEF"
n=client_tcp.send(texte.encode(encoding = 'UTF-8'))
inData=client_tcp.recv(1024)
data = inData.decode()
print ("[" + data + "]")
if 'OK' == data:
print('good')
else:
print('bad')
#texte = "DEF"
texte = "ABC"
n=client_tcp.send(texte.encode(encoding = 'UTF-8'))
inData=client_tcp.recv(1024)
data = inData.decode()
print ("[" + data + "]")
if 'OK' == data:
print('good')
else:
print('bad')
client_tcp.close()
Client's output Order ABC DEF:
[OK]
good
[OK]
good
Client's output Order DEF ABC:
[FAIL]
bad
[FAIL]
bad
My current code is as follows:
from socket import *
import threading
import datetime
import csv
import time
global clist
clist = []
HOST = "ip"
PORT = 1876
s = socket(AF_INET, SOCK_STREAM)
s.bind((HOST, PORT))
s.listen(5)
def clientHandler():
print("Thread successful\n")
connect, address = s.accept()
clist.append(connect)
iplist = open("iplist.txt","a+")
iplist.write(str(address)+"\n")
iplist.close()
print('IP Recorded.')
while 1:
try:
data = connect.recv(1024)
data = data.decode()
current_date = time.strftime("%d-%m")
log = open(current_date+"log.txt","a+")
print("("+time.strftime("%H:%M:%S")+")","> ", data)
log.write("> "+data+"\n")
log.close()
data = data.encode()
for item in clist:
item.sendall(data)
except: #handles clients leaving and fixes reconnect bug, succesfully removing them from clist
clist.remove(connect)
print(address, 'has disconnected.')
break
print("Server started...")
for i in range(5):
makeThread = threading.Thread(target=clientHandler)
makeThread.start()
aliveList = threading.enumerate()
print(aliveList)
My problem is that once clients join or rejoin (x5) the server won't allow any more connections (because the threads of my clientHandler function have been used). Would I have to close the threads and some how make them reusable to allow more clients to join/rejoin? (How would I do this?)
Also, could anybody recommend improvements to my code/guide me on the right path with socket programming, as I am very new to all this.
All help appreciated,
cheers.
I suggest using threading.activeCount() to enumerate your threads.
Lets say you want 5 clients max , then activeCount() should be <= 6 ( five clients and the main thread )
Try this loop :
while True :
try :
if threading.activeCount() < 6 :
makeThread = threading.Thread(target=clientHandler)
#makeThread.daemon = True ## uncomment this line if you want your threads to terminate when the main thread dies ##
makeThread.start()
print('Active clients: {}'.format(threading.activeCount() - 1))
except KeyboardInterrupt :
print('terminated')
break
Now when clientHandler() returns , there is room for the next client .
I got a small python program that communicates with an EV3 robot (lego's robot) via BT. The program sends the EV3 a number 1/2 or 3, the robot makes a predefined movement and send back 'A' to indicate that the movement is done and that it is ready for next command.
The system works great but once in a while the python app crushes with this error message:
'An established connection was aborted by the software in your host machine.' this comes from socket.recv that is called inside btListener() thread.
The relevant python parts:
import bluetooth
from gmail import *
import re
from gtts import gTTS
from time import sleep
import pygame
import serial
import thread
import os
import ftplib
from StringIO import StringIO
from blynkapi import Blynk
def a(): #Send 'a' to 'Status' mailbox
print "Send a to robot"
for i in commandA:
client_sock.send(chr(i))
sleep(1)
def b(): # Send 'b' to 'Status' mailbox
def c(): # Send 'c' to 'Status' mailbox
def clear(): # Send clear array to 'Status' mailbox
for i in clearArray:
client_sock.send(chr(i))
def btListener():
# Listen for end of run reply from the EV3
global ev3Flag, listenFlag
while True:
if listenFlag and (not ev3Flag):
try:
data = client_sock.recv(1024) #Check if EV3 is ready for new command
if data[-2] == 'A':
ev3Flag = True
print "Received 'Ready' from EV3 "
sleep(1)
except Exception as e:
print(e)
print "Failed to read data from socket"
def queueHandler():
# Read next command from QueueArray, call sendFunc and clear the queue
global ev3Flag, listenFlag, queueArray
while True:
if len(queueArray) > 0 and ev3Flag:
sendFunc(queueArray[0])
queueArray.pop(0)
def sendFunc(cmd):
#Send the next command on QueueArray to the EV3
global ev3Flag, listenFlag
if cmd == 1:
try:
ev3Flag = False
listenFlag = False
a()
listenFlag = True
sleep(3)
clear() # clear the EV3 btsocket with a default message
except Exception as e:
print "Error on sendFunc cmd = 1"
print(e)
elif cmd == 2:
try:
except Exception as e:
elif cmd == 3:
try:
except Exception as e:
if __name__ == "__main__":
# Blynk setup
blynk = Blynk(auth_token)
switch1 = Blynk(auth_token, pin = "V0")
switch2 = Blynk(auth_token, pin = "V1")
switch3 = Blynk(auth_token, pin = "V2")
print "Blynk connected"
queueArray = [] # Queue array to hold incoming commands
listenFlag = True # Listen to message from EV3
ev3Flag = True # EV3 ready for new command flag
# BT CONNECTION WITH EV3 #
print "Searching for BT connections: "
nearby_devices = bluetooth.discover_devices()
for bdaddr in nearby_devices:
print bdaddr + " - " + bluetooth.lookup_name(bdaddr)
if target_name == bluetooth.lookup_name(bdaddr):
target_address = bdaddr
break
server_sock = bluetooth.BluetoothSocket(bluetooth.RFCOMM)
port = 1
server_sock.bind(("", port))
server_sock.listen(1)
client_sock, address = server_sock.accept()
print "Accepted connection from ", address
if target_address is not None:
print "found target bluetooth device with address ", target_address
else:
print "could not find target bluetooth device nearby"
# END BT CONNECTION WITH EV3 #
try:
thread.start_new_thread(queueHandler, ())
except Exception as e: print(e)
try:
thread.start_new_thread(btListener, ())
except Exception as e: print(e)
while True:
res1 = switch1.get_val()
res2 = switch2.get_val()
res3 = switch3.get_val()
if (int)(res1[0]) == 1:
print "Add 1 to queue"
queueArray.append(1)
if (int)(res2[0]) == 1:
print "Add 2 to queue"
queueArray.append(2)
if (int)(res3[0]) == 1:
print "Add 3 to queue"
queueArray.append(3)
Edit 1:
I tested it a bit more and it seems that the crush happens when the program tries to recv data and send data the same time. (via the clear() or a()/b()/c() functions), could that be the situation?
I'm new to sockets so the first solution that comes in mind is create a flag to limit the action of the socket, is there a better/smarter way to keep that from happening?
Edit 2:
I moved the 'listenFlag = True' line inside sendFunc() to after my call to clear() and it seems to solve the problem which was probably due to the python program trying to receive and sand at the same time.
I moved the 'listenFlag = True' line inside sendFunc() to after my call to clear() and it seems to solve the problem which was probably due to the python program trying to receive and sand at the same time.
Hello I've been trying to make my python sock server connection counter to go down
but I can't figure out how I can do this
def client_thread(conn):
while True:
conn.send("Command: ")
data = conn.recv(1024)
if not data:
break
reply = "" + data
conn.sendall("\r")
if data == "!* Connections":
conn.sendall("[+] Clients Connected: %s \r\n" % (clients))
conn.close()
while True:
conn, addr = sock.accept()
clients = clients + 1
start_new_thread(client_thread, (conn,))
sock.close()
I needn't show you all of the code because its irrelevant to this issue,
I have provided the code that make's the counter go up when a new connection connects, but as said before I don't know how to make it go down when a connection leaves.
When trying to find solutions online there show's nothing that can help my issue
Here is a small sample how to realize a client counter with the select.select function. I actually took it from the great article select – Wait for I/O Efficiently on pymotw.com and added a client counter. Basically you look for readable sockets and try to receive data from them. If a socket returns nothing it means it has been closed and can be removed from the client list.
import queue
import socket
import select
clients = 0
sock = socket.socket()
sock.bind(('localhost', 5000))
sock.listen(5)
inputs = [sock]
outputs = []
msg_queues = {}
while inputs:
readable, writable, exceptional = select.select(
inputs, outputs, msg_queues)
for s in readable:
if s is sock:
conn, addr = sock.accept()
print('new connection from ', addr)
conn.setblocking(0)
inputs.append(conn)
msg_queues[conn] = queue.Queue()
# increment client counter
clients += 1
print('Clients: ', clients)
else:
# try to receive some data
data = s.recv(1024)
if data:
# if data available print it
print('Received {} from {}'.format(data, s.getpeername()))
msg_queues[s].put(data)
# add output channel for response
if s not in outputs:
outputs.append(s)
else:
# empty data will be interpreted as closed connection
print('Closing connection to ', s.getpeername())
# stop listening for input on the connection
if s in outputs:
outputs.remove(s)
# remove from inputs
inputs.remove(s)
s.close()
# decrement client counter
clients -= 1
del msg_queues[s]
print('Clients: ', clients)
I have a program hande some devices in network. the program create a process for each device and each process run socket.recv function in a loop to receive messages from connected device.
when I turn device off and then turn it on, the connection between program and device would be lost but the recv function would not return any things or raise any exception and the process stay blocked.
How can handle this problem
this is my code :
if __name__ == '__main__':
ip = sys.argv[1]
port = sys.argv[2]
pingInterval = float(sys.argv[3])
deviceId = sys.argv[4]
print("A card reader started for ", ip)
Thread(target=setThePingerThread, args=(pingInterval,)).start()
while True:
clientsock = socket (AF_INET, SOCK_STREAM)
connectionSuccessful = False
while not connectionSuccessful:
try:
clientsock.connect((ip, int(port)))
connectionSuccessful = True
print('socket connected to ', ip, port)
except Exception as e:
print('Can''t connect to the device! device ip =>', ip)
time.sleep(5000)
pass
try:
mybuffer = bytes()
data = bytes()
cardNumbers = []
while True:
mybuffer = clientsock.recv(100)
data = data + mybuffer
cardNumbers, data = retreiveCardNumbers(data)
#print('debug: cardNumbers=', cardNumbers, ' data=',data, ' data-decoded=',data.decode("ascii"))
for cardNumber in cardNumbers:
print('A card hit:', cardNumber)
sendToQueue(cardNumber, deviceId)
except Exception as e:
print('Error processing card number! device ip =>', ip, e)
Referring to
the process stay blocked
I do not know the code of setThePingerThread but I guess the error is solved with this:
thread = Thread(target=setThePingerThread, args=(pingInterval,))
thread.deamon = True
thread.start()
thread.deamon is usually False which makes the program wait for the end of that thread.