Python, TCP, Server and client - python-3.x

I have problem with TCP (Server and Client.) over python3.
What does i do wrong?
my code is in TCP Server:
import socket
server = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
ip = socket.gethostbyname("127.0.0.1")
port = 8892
address=(ip,port)
server.bind(address)
server.listen(1)
print("[*] Started listening on" , ip, ":", port)
client,addr = server.accept()
print("[*] Got Connection from", addr[0], ":", addr[1])
while True:
data = client.recv(1024)
data = data.decode('utf-8')
print("[*] Received ", data, " from the client")
print("[*] Processing data")
if data == "hello":
client.send("Hello client")
print("[*] Processing done\n[*] Reply sent")
elif data == "disconnect":
client.send("Goodbye")
client.close()
break
else:
client.send("Invalid type")
print("Processing done Invalid data \n[*] Reply sent")
my code is in TCP Client:
import socket
client=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
ip = socket.gethostbyname("127.0.0.1")
print(ip)
port=8892
address=(ip,port)
client.connect(address)
while True:
message = input()
client.send(message.encode('utf-8'))
print(client.recv(1024))
Erorr message:
Traceback (most recent call last): File "tcpServer.py", line 25, in
client.send("Invalid type") TypeError: a bytes-like object is required, not 'str'
Can some one help me please, what can i do?
Thanks for helping me. :)

in python 3 you are no more sending/reading characters or string, but byte-array (or bytes).
You might also need to manage encoding (utf-8 <-> bytes).
ex:
>>> s = "énorme"
>>> b = s.encode("utf-8")
>>> b
b'\xc3\xa9norme'
and use the bytes.decode() to reverse it.
For your very trivial case, you can use direcly bytes string as b"hello", as plain ASCII string are converted "as-is" to bytes.
client.send("Hello client") will become client.send(b"Hello client")
But don't go too deeper with this solution.
I personally allow this usage when using commands to talk to some hardware, but absolutely not for a chat or text exchange.

Related

How to send integer through socket in python

Actually, I want to send integers through the server to client and vice versa. So that I can apply some operations on them on the client/server side. But whenever I a try to send integers, the server or client gets automatically destroyed even without sending the message. I have also used a while loop but it's not working as it was supposed to do?
Also, it works fine when I send strings (encoded)
--->server side<----
import socket
s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
print("--------------->SERVER<-----------------")
ip = "127.0.0.1"
port = 8080
s.bind((ip,port))
s.listen(2)
conn,addr = s.accept()
print("CONNECTED WITH THE CLIENT\n")
while True:
#for sending message
temp_msg = input("SERVER - ")
message = int(temp_msg.encode())
conn.send(message)
#for receiving message
rec_msg = conn.recv(1024)
print("CLIENT - ",rec_msg, " type = ", type(rec_msg))
---> client side <----
import socket
print("--------->CLIENT<----------------")
s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
ip = "127.0.0.1"
port = 8080
s.connect((ip,port))
print("CLIENT1 IS CONNECTED TO THE SERVER")
while True:
#for receiving message
rec_msg = s.recv(1024)
rec_msg = rec_msg
print("SERVER - ", rec_msg," type = ", type(rec_msg))
#for sending message
temp_msg = input("CLIENT - ")
message = int(temp_msg)
s.send(message)
----> output of client side code after sending the initial message through server.py<------
--------->CLIENT<----------------
CLIENT1 IS CONNECTED TO THE SERVER
SERVER - b'' type = <class 'bytes'>
CLIENT -
I found a very simple method to send integer by converting them to string before sending, and then change back to to the integer format after receiving them through a socket.
You can do this by following the below method.
#server side:
num=123
# convert num to str, then encode to utf8 byte
tcpsocket.send(str(num).encode('utf8'))
#client side
data = tcpsocket.recv(1024)
# decode to unicode string
strings = data.decode('utf8')
#get the num
num = int(strings)

Multi-client TCP socket server (server sends query upon connection then waits for client response + polls client)

I modified the code above from what Torxed posted in the URL: Sending string via socket (python)
I used this as a base as want a multi-threading python3 server. I'm still learning Python so am getting a little stuck.
I've got 2 threads working where the 1st (a background) thread sends a UDP broadcast to inform clients that the source host (the python server) is waiting for client connections.
The client detects the UDP broadcast (on port 1300) & initiates a new TCP session to port 1200. I have got the python server to immediately send some bytes (bytes as not ascii) to the client which 'asks' the client to identity itself upon connection (the client does not initiate the conversation other than establishing the TCP session). In this case the client host is a solar inverter.
The client responds with some basics such as it's serial number, software version, etc which I want to store. Currently I'm not able to store the reply in a variable as it's byte sequence, not ascii so I'm currently writing the datagram to a local file until I figure out how to unpack the byte sequence & save in variables associated to the client session. This will be used to aid identifying which data-set is associated to which client.
Every 15 seconds after that, I want the python server to send some more bytes (again bytes not ascii) which will inform the client to reply with some PV (solar) data.
The client will reply with the PV data which I want to store associated to the client session.
Lastly if an event occurs on the client (inverter such as AC loss power) it will send to the server another datagram in the established TCP session a specifically formatted byte sequence so the server needs to handle an independent response from the client which will be to initiate sending an email (to me) containing the event type. Is it better to use a single recv datagram handler with something like a case statement to identify the response then process it accordingly (but the server must first receive the client's id).
I want the TCP session to remain open indefinitely but also support a 2nd inverter to connect too & allow them should connectivity is temporally interpreted to re-connection without issue.
Any help appreciated as I'm stuck with being unable to read the response from the client.
Here is what I currently have:
#!/usr/bin/env python3
# need threading support to run broadcast UDP 1300 thread
from threading import *
from socket import *
# import time for sleep/delay timers
import time
# Now we can create socket object
serversocket = socket(AF_INET, SOCK_STREAM)
#serversocket.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)
#serversocket.setsockopt(SOL_SOCKET, SO_BROADCAST, 1)
# Set the IP address and port to listen on
HOST = "192.168.1.11"
PORT = 1200
# Bind the socket on the interface/port
serversocket.bind((HOST, PORT))
# This is the client thread allowing multiple clients to connect
class client(Thread):
# This section is what will run in the background
def background():
while True:
cs.sendto(b'\x55\xaa\x00\x40\x02\x00\x0b\x49\x20\x41\x4d\x20\x53\x45\x52\x56\x45\x52\x04\x3a', ("192.168.1.255", 1301))
time.sleep(5)
# This section is what will run in the foreground
def __init__(self, socket, address):
Thread.__init__(self)
self.sock = socket
self.addr = address
self.start()
def run(self):
while True:
msg = (b'\x55\xaa\x01\x03\x02\x00\x00\x01\x05')
self.sock.send(msg)
#Open recv.txt file in write mode
recvdatafile1 = open("recv1.txt", "wb")
print("Destination file name will be recv1.txt on the server\n")
# Receive intiate data from client side
# RecvData = self.sock.recv(1024)
while True:
recvdatafile1.write(RecvData)
# recvdatafile1.write(self.sock.recv(1024))
RecvData = self.sock.recv(1024)
# Request initial configuration information (replies with S/N, model number, etc
#msg = (b'\x55\xaa\x01\x03\x02\x00\x00\x01\x05')
#conn.send(msg)
# Close the file opened at server side once copy is completed
recvdatafile1.close()
print("\n File has been copied successfully \n")
#Open recv.txt file in write mode
recvdatafile2 = open("recv2.txt", "wb")
print("Destination file name will be recv2.txt on the server\n")
# Request PV data
msg = (b'\x55\xaa\x01\x02\x02\x00\x00\x01\x04')
conn.send(msg)
# Receive any data from client side
RecvData = conn.recv(1024)
while RecvData:
recvdatafile2.write(RecvData)
RecvData = conn.recv(1024)
# Close the file opened at server side once copy is completed
recvdatafile2.close()
print("\n File has been copied successfully \n")
# Close connection with client
conn.close()
print("\n Server closed the connection \n")
time.sleep(3)
# Come out from the infinite while loop as the file has been copied from client.
#break
serversocket.listen(5)
print("Server is listing on port:", PORT, "\n")
while 1:
clientsocket, address = serversocket.accept()
client(clientsocket, address)
print ("connection found!")
data = clientsocket.recv(1024).decode()
print (data)
b = threading.Thread(name='background', target=background)
f = threading.Thread(name='foreground', target=foreground)
b.start()
f.start()
Server Output:
user#server:~# python3 ./Samil_Solar_River_Monitor_Server.py
Server is listing on port: 1200
connection found!
Destination file name will be recv1.txt on the server
Exception in thread Thread-1:
Traceback (most recent call last):
File "/usr/lib/python3.6/threading.py", line 916, in _bootstrap_inner
self.run()
File "./Samil_Solar_River_Monitor_Server.py", line 62, in run
recvdatafile1.write(RecvData)
UnboundLocalError: local variable 'RecvData' referenced before assignment
Traceback (most recent call last):
File "./Samil_Solar_River_Monitor_Server.py", line 109, in <module>
data = clientsocket.recv(1024).decode()
UnicodeDecodeError: 'utf-8' codec can't decode byte 0xaa in position 1: invalid start byte
user#server:~#
Client Output:
user#client:~$ python3 test-solar-client.py 192.168.1.11
################## Below rcved from srv ##################
b'U\xaa\x01\x03\x02\x00\x00\x01\x05' <-- This is good/correct
################## Below rcved from srv ##################
b'' <-- this & below appears when traceback on server occurs
Traceback (most recent call last):
File "test-solar-client.py", line 47, in <module>
s.send(SendData)
BrokenPipeError: [Errno 32] Broken pipe
user#client:~$

how do i make my server able to read data which is sent by client

here i am making server
my_selector = selectors.DefaultSelector()
keep_running = True
server_address = ('localhost', 1040)
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.setblocking(False)
sock.bind(server_address)
sock.listen(5)
my_selector.register(sock, selectors.EVENT_READ, data=None)
this accept function make new connection
def accept(sock):
# print("Accept Function")
new_connection, addr = sock.accept()
print("Connection established.......")
new_connection.setblocking(False)
my_selector.register(new_connection, selectors.EVENT_READ | selectors.EVENT_WRITE, data=None)
this read function reads data sent by client
def read(connection, mask):
global keep_running
print("Read Function")
if mask & selectors.EVENT_READ:
recv_data = connection.recv(1024)
if recv_data:
print("Message received ", recv_data.decode("utf-8"))
else:
print("Message not received")
my_selector.unregister(connection)
connection.close()
keep_running = False
this loop controls my server
while keep_running:
for key, mask in my_selector.select(timeout=None):
if key.data is None:
accept(key.fileobj)
else:
read(key, mask)
my_selector.close()
my question is when server and client run if server gets a new client it control goes to accept function
or if server gets data it goes to read function this programme shows error
client programme does not show any error client programme only send data
please tell me how to fix this error and i am working on windows 10
Error----OSError: [WinError 10022] An invalid argument was supplied
Try looking at this post maybe it helps you :)
The first answer on that where the guy is having the same error says:
Bind the socket before calling connection.recvfrom(65536) using connection.bind((YOUR_IP, PORT)).
OSError: [WinError 10022] An invalid argument was supplied - Windows 10 Python

Python Can't decode byte : Invalid start byte

So I'm building this socket application, and it works just fine on my computer. But when i start server socket on another laptop, it just crashes with a invalid start byte error:
How do i proper encode the program to work with all laptops
This is the error i get on :
Other laptops.
My laptop.
I have tried to change the encoding, but I'm just not quite sure where i have to change it.
Class Listener:
def __init__(self):
self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.server_address = (socket.gethostbyname(socket.gethostname()), 10000)
self.sock.bind(self.server_address)
print(f"LISTENER : {str(self.server_address[0])} port {str(self.server_address[1])}")
def listen(self):
self.sock.listen(1)
while True:
print("Connection Open")
print(" Waiting for connections")
self.connection, self.client_address = self.sock.accept()
try:
print(f"Connection from {str(self.client_address)}")
while True:
data = self.connection.recv(1024)
if data:
message = str(data)
if not "print" in message.lower(): # This just checks if the client wants to print system information from the server
Validate(message) # this checks for a command the server have to do
else:
self.connection.sendall(pickle.dumps(self.computerinfomation))
else:
self.listen()
except Exception as e:
print(e)
I want it to work on other laptops as well, and i just cant see why it wont.
Furas came with a solution.
I changed the
message = str(data)
to
message = str(data, encoding="utf-8")
I did the same on the client side
Not going to lie. I just changed the encoding = utf-16.
Example:
df = pd.read_csv(C:/folders path/untitled.csv, encoding = "utf-16")

Python36 and sockets

So I'm connected to an IRC chat using socket.connec
I log in by passing my variables via socket.send
The log in is successful and then I sit in a while true loop using
Socket.recv(1024)
If I just continually print the response everything looks fine, but let's say I want to add to the end of the string... I noticed that socket.recv doesn't always get the full message (only grabs up to 1024 as expected) and the remainder of the message is in the next iteration of the loop.
This makes its it impossible to process the feedback line by line.
Is there a better way to constantly read the data without it getting trunked? Is it possible to figure out the size of the response before receiving it so the buffer can be set dynamically?
TCP is a stream-based protocol. Buffer the bytes received and only extract complete messages from the stream.
For complete lines, look for newline characters in the buffer.
Example server:
import socket
class Client:
def __init__(self,socket):
self.socket = socket
self.buffer = b''
def getline(self):
# if there is no complete line in buffer,
# add to buffer until there is one.
while b'\n' not in self.buffer:
data = self.socket.recv(1024)
if not data:
# socket was closed
return ''
self.buffer += data
# break the buffer on the first newline.
# note: partition(n) return "left of n","n","right of n"
line,newline,self.buffer = self.buffer.partition(b'\n')
return line + newline
srv = socket.socket()
srv.bind(('',5000))
srv.listen(1)
conn,where = srv.accept()
client = Client(conn)
print(f'Client connected on {where}')
while True:
line = client.getline()
if not line:
break
print(line)
Example client:
s=socket()
s.connect(('127.0.0.1',5000))
s.sendall(b'line one\nline two\nline three\nincomplete')
s.close()
Output on server:
Client connected on ('127.0.0.1', 2667)
b'line one\n'
b'line two\n'
b'line three\n'

Resources