Trying to send a string encoded in utf-8 using sockets - python

I am trying to send a string encoded in utf to a server and get a response from it.However I am not able to get any response as i think the string I'm sending from the client has not been encoded properly.
Here is what I've done to encode the string:
a= "!##$%"
u = a.encode('utf-8')
s=socket.socket()
s.connect((ipAddr,portNum))
a=s.recv(1024)
print (a)//prints ok
s.send(u)
s.recv(1024)#blank
print (s.recv(1024))
JAVA:
Socket smtpSocket = new Socket(ipAddr,portNum);
smtpSocket.setSoTimeout(1000*30);
is = new BufferedReader(new InputStreamReader(smtpSocket.getInputStream()));
service=new DataOutputStream(smtpSocket.getOutputStream());
String response = is.readLine();
System.out.println(response);
if(response.startsWith("okE"))
{
service.writeUTF(x);
}
response = is.readLine();
System.out.println(response);

It seems that you server is writen in Java, I have write some server code that fit for you Java client.
ServerSocket serverSocket = new ServerSocket(50001);
serverSocket.setSoTimeout(3 * 1000);
Socket socket = serverSocket.accept();
System.out.println("Receive new connection: " + socket.getInetAddress());
BufferedWriter out = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
DataInputStream in = new DataInputStream(socket.getInputStream());
out.write("ok");
// out.newLine();
out.flush();
String input = in.readUTF();
System.out.println(input);
out.write(input);
// out.newLine();
out.flush();
And the reason of getting nothing response in Python client is in.readUTF(), According to https://stackoverflow.com/a/48266697/7944150, you should send the length of message before.
import socket
ipAddr = 'localhost'
portNum = 50001
a = "!##$%"
u = a.encode('utf-8')
s = socket.socket()
s.connect((ipAddr, portNum))
a = s.recv(1024)
print(a)
s.send(len(u).to_bytes(2, byteorder='big'))
s.send(u)
a = s.recv(1024)
print(a)
And I get the response:
b'ok'
b'!##$%'

Related

sockets module in python not properly sending requests?? sockets newbie here

so i have been trying to create a script for a capture the flag level, and lately i have been completely stumped as to how this has not been working out.
#
# Connect to alien server ('localhost', 10000)
#
# Then send each of these values...
# USER
# aliensignal
# PASS
# unlockserver
# SEND
# moonbase
# END
# ...and receive the response from each.
#
# Note: You must receive data back from the server after you send each value
#
from signal import signal, SIGPIPE, SIG_DFL
signal(SIGPIPE,SIG_DFL)
import socket
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect(('localhost', 10000))
header = "USER: aliensignal"
header1 = "PASS: unlockserver"
header2 = "SEND: moonbase"
header3 = "END"
req = "POST / HTTP/1.1\r\{}\r\n\r\n".format(header)
req1 = "POST / HTTP/1.1\r\{}\r\n\r\n".format(header1)
req3 = "POST / HTTP/1.1\r\{}\r\n\r\n".format(header2)
req4 = "POST / HTTP/1.1\r\{} \r\n\r\n".format(header3)
request1 = bytes(req, "utf-8")
sock.send(request1)
response = sock.recv(2048)
print(response)
request2 = bytes(req1, "utf-8")
sock.send(request2)
response2 = sock.recv(2048)
print(response2)
request3 = bytes(req3, "utf-8")
sock.send(request3)
response3 = sock.recv(2048)
print(response3)
request4 = bytes(req4, "utf-8")
sock.send(request4)
response4 = sock.recv(2048)
print(response4)
sock.close()
I try to setup the socks variable to be used to call to for socket operations, and then i try to define all of the requests that will be made, and type-cast them into bytes type. and i send the requests while waiting for a response, however none is given, and the output just remains blankscreenshot of code editor
ive tried to combine the type-casted request values into a single byte value and then using the socks.sendall(val) to no avail, ive tried to put the values itself into a single string to no avail

How do I achieve Python TCP Socket Client/Server with Communications Encrypted?

Backstory: what I have done
{Codes at the bottom} I've already coded the multithreaded client and server programs using python socket, with the help of the following sites:
I. Echo Client and Server
II. Socket Server with Multiple Clients | Multithreading | Python
III. Python Socket Receive Large Amount of Data
Regarding Encryption & Decryption
(1) Exactly at what places in my codes should I encrypt/decrypt my message? Do
I encrypt the messages themselves after the user inputs or do I encrypt the byte streams after the input messages have been encoded?
(2) And how am I supposed to encrypt/decrypt the communication properly and efficiently? (It'd be nice to see code solutions with explanation, many thanks)
My Codes Currently
_server.py
import socket
import os
from _thread import *
import struct # Here to convert Python data types into byte streams (in string) and back
# ---- To Avoid Message Boundary Problem on top of TCP protocol ----
def send_msg(sock: socket, msg): # ---- Use this to send
# Prefix each message with a 4-byte length (network byte order)
msg = struct.pack('>I', len(msg)) + msg
sock.sendall(msg)
def recv_msg(sock: socket): # ---- Use this to receive
# Read message length and unpack it into an integer
raw_msglen = recvall(sock, 4)
if not raw_msglen:
return None
msglen = struct.unpack('>I', raw_msglen)[0]
# Read the message data
return recvall(sock, msglen)
def recvall(sock: socket, n: int):
# Helper function to receive n bytes or return None if EOF is hit
data = bytearray()
while len(data) < n:
packet = sock.recv(n - len(data))
if not packet:
return None
data.extend(packet)
return data
# ---- Server Communication Setup
HOST = '127.0.0.1' # Standard loopback interface address (localhost)
PORT = 65432 # Port to listen on (non-privileged ports are > 1023)
ThreadCount = 0
try: # create socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
print ("Socket successfully created")
except socket.error as err:
print ("socket creation failed with error %s" %(err))
try: # bind socket to an address
s.bind((HOST, PORT))
except socket.error as e:
print(str(e))
print('Waitiing for a Connection..')
s.listen(3)
def threaded_client(conn: socket):
conn.send(str.encode('Welcome to the Server'))
while True:
# data = conn.recv(2048) # receive message from client
data = recv_msg(conn)
reply = 'Server Says: ' + data.decode('utf-8')
if not data:
break
# conn.sendall(str.encode(reply))
send_msg(conn, str.encode(reply))
conn.close()
while True:
Client, addr = s.accept()
print('Connected to: ' + addr[0] + ':' + str(addr[1]))
start_new_thread(threaded_client, (Client, )) # Calling threaded_client() on a new thread
ThreadCount += 1
print('Thread Number: ' + str(ThreadCount))
s.close()
_client.py
import socket
import struct # Here to convert Python data types into byte streams (in string) and back
# ---- To Avoid Message Boundary Problem on top of TCP protocol ----
def send_msg(sock: socket, msg): # ---- Use this to send
# Prefix each message with a 4-byte length (network byte order)
msg = struct.pack('>I', len(msg)) + msg
sock.sendall(msg)
def recv_msg(sock: socket): # ---- Use this to receive
# Read message length and unpack it into an integer
raw_msglen = recvall(sock, 4)
if not raw_msglen:
return None
msglen = struct.unpack('>I', raw_msglen)[0]
# Read the message data
return recvall(sock, msglen)
def recvall(sock: socket, n: int):
# Helper function to receive n bytes or return None if EOF is hit
data = bytearray()
while len(data) < n:
packet = sock.recv(n - len(data))
if not packet:
return None
data.extend(packet)
return data
# ---- Client Communication Setup ----
HOST = '127.0.0.1' # The server's hostname or IP address
PORT = 65432 # The port used by the server
try:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
print ("Socket successfully created")
except socket.error as err:
print ("socket creation failed with error %s" %(err))
print('Waiting for connection')
try:
s.connect((HOST, PORT))
except socket.error as e:
print(str(e))
Response = s.recv(1024)
while True:
Input = input('Say Something: ')
# s.send(str.encode(Input))
send_msg(s, str.encode(Input))
# Response = s.recv(1024)
Response = recv_msg(s)
print(Response.decode('utf-8'))
s.close()
You only need to Encrypt the Message itself. I would use RSA to Encrypt the Messages.
If you plan on using multiple Servers, you can open a second Port and if someone connects to it, the Server/Host. Sends the Public Key to the Client.
After that, the Client sends his Public key to the Server.
Now Server and Client switch Ports, and Communicate over there while using the Public key of the other to Encrypt the Messages and decrypt them with their Private key.
You can also Hard-code the Public Keys, if you only have one Server and one Client.
A good Module for RSA Encryption is PyCrytodome.
Here is an Example of to encrypt messages with PyCrytodome.
from Crypto.PublicKey import RSA
from Crypto.Cipher import PKCS1_OAEP
def encrypt(pk_receiver, message):
key = RSA.import_key(pk_receiver)
cipher = PKCS1_OAEP.new(key)
c = cipher.encrypt(message.encode())
return c
def decrypt(sk, c):
key = RSA.import_key(sk)
cipher = PKCS1_OAEP.new(key)
m = cipher.decrypt(c)
return m
def generate_sk(key_length):
key = RSA.generate(key_length)
with open('./secret_key.pem', 'wb') as f:
f.write(key.export_key(format='PEM'))
return key
def generate_pk(sk):
pk = sk.public_key()
with open('./public_key.pem', 'wb') as f:
f.write(pk.export_key(format='PEM'))
return

How to make client and server send and accept different message lengths in python

In my python homework, I have to make a server and some clients.
My problem comes from the fixed string size in the packing/unpacking process on both the server and client sides. I want to send messages with two different sized strings.
Here is my simplified code:
client:
import socket
import struct
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock:
sock.connect(('127.0.0.1', 5555))
str1 = b"A"
msg = (str1, 3)
msg_packed = struct.Struct("1s I").pack(*msg) #the fixed string size is not a problem here
sock.sendall(msg_packed)
reply_packed = sock.recv(1024)
reply = struct.Struct("2s I").unpack(reply_packed) #since the string in the reply can be 'Yes' or 'No' what is 2 and 3 character. I don't know hot make it accept both.
print(reply)
and the Server:
import socket
import select
import struct
srv = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
srv.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
srv.bind(('0.0.0.0', 5555))
srv.listen()
socks = [srv]
while True:
readable, writeable, err = select.select(socks, [], [], 0.1)
for s in readable:
if s == srv:
client, client_address = srv.accept()
print("New client from: {} address".format(client_address))
socks.append(client)
else:
msg_packed = s.recv(1024)
if msg_packed:
for sock in socks:
if sock == s and sock != srv:
msg = struct.Struct("1s I").unpack(msg_packed)
if (msg[0] == b'A'): #In here the reply message need to be 'Yes' or 'No'
reply = (b'Yes', msg[1] * msg[1])# the struct.Struct("2s I").pack(*reply) will not going to accept this
else:
reply = (b'No', msg[1] + msg[1])
reply_packed = struct.Struct("2s I").pack(*reply)
sock.send(reply_packed)
else:
print("Client disconnected")
socks.remove(s)
s.close()
Is there any way to be able to send both 2 and 3 string lengths? And if yes, how should I change my code?
EDIT: You can just dynamically set the format string of the struct. Here is a simple example:
str1 = b"Yes"
str2 = b"No"
msg_packed1 = struct.Struct("{}s".format(len(str1))).pack(str1)
msg_packed2 = struct.Struct("{}s".format(len(str2))).pack(str2)
In your example it would be
reply_packed = struct.Struct("{}s I".format(len(reply[0]))).pack(*reply)
I got this idea from packing and unpacking variable length array/string using the struct module in python

Client cannot receive UDP message

I am a beginner of socket programming using python. I am working on my course project. Part of my project requires sending and receiving UDP messages with different port. The server program called robot is provided and I need to write the client program called student which can interact with the robot. Thus, I cannot show all source code in the server program.
This is the part related to the UDP socket in the server program
############################################################################# phase 3
# Create a UDP socket to send and receive data
print ("Preparing to receive x...")
addr = (localhost, iUDPPortRobot)
s3 = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s3.bind(addr)
x, addr = s3.recvfrom(1)
print ("Get x = %d" % (int(x)))
############################################################################# phase 3
time.sleep(1)
print ("Sending UDP packets:")
messageToTransmit = ""
for i in range(0,int(x) * 2):
messageToTransmit += str(random.randint(0,9999)).zfill(5)
print ("Message to transmit: " + messageToTransmit)
for i in range(0,5):
s3.sendto(messageToTransmit.encode(),(studentIP,iUDPPortStudent))
time.sleep(1)
print ("UDP packet %d sent" %(i+1))
############################################################################# phase 4
This is my client program. s3 is the UDP socket. I can send message to the server program successfully but I cannot receive the message from it. Is this due to the difference in the ports? If yes, what should I do in order to fix it?
import os
import subprocess
import socket
import random
import time
sendPort = 3310
localhost = '127.0.0.1'
socket.setdefaulttimeout(10)
command = "python robot_for_python_version_3.py"
subprocess.Popen(command)
print("ROBOT IS STARTED")
sendSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sendSocket.connect((localhost, sendPort))
studentId = '1155127379'
sendSocket.send(studentId.encode())
s_2Port = sendSocket.recv(5)
sendSocket.close()
s_2 = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s_2.bind((localhost, int(s_2Port)))
s_2.listen(5)
s2, address = s_2.accept()
s_2.close()
step4Port = s2.recv(12)
iUDPPortRobot, dummy1 = step4Port.decode().split(",")
iUDPPortStudent, dummy2 = dummy1.split(".")
s3 = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
num = random.randint(5,10)
time.sleep(3)
s3.sendto(str(num).encode(), (localhost, int(iUDPPortRobot)))
print("Test1")
charStr = s3.recvfrom(1024)
print("Test2")
print(charStr)
exit()
The reason why you are not receiving the message is because the server sends it to an endpoint that is not listening for messages. As the protocol is UDP (no guarantees, etc.), the server sends the message successfully to a non-listening endpoint, while the listening endpoint waits forever.
In more detail, addr as returned by x, addr = s3.recvfrom(1) is not (studentIP, iUDPPortStudent). Try the following to see the difference (note that you have omitted the piece where iUDPPortRobot is defined and shared, I set it to 50000 for illustration purposes):
# in one interactive session 1 (terminal), let's call it session 1
>>> import socket
>>> import random
>>> import time
>>>
>>> iUDPPortRobot = 50000
>>> addr = ('localhost', iUDPPortRobot)
>>> s3 = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
>>> s3.bind(addr)
>>> x, addr = s3.recvfrom(1) # <= this will block
# in another interactive session (terminal), let's call it session 2
>>> import socket
>>> import random
>>> import time
>>>
>>> iUDPPortRobot = 50000
>>> s3 = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
>>> num = random.randint(5,10)
>>> s3.sendto(str(num).encode(), ('localhost', int(iUDPPortRobot))) # <= this will unblock recvfrom in session 1, i.e., the message got received
1
# back to session 1
>>> addr <= check address, this is the main issue you are facing
('127.0.0.1', 60911)
>>> messageToTransmit = ""
>>> for i in range(0,int(x) * 2):
... messageToTransmit += str(random.randint(0,9999)).zfill(5)
...
>>> print ("Message to transmit: " + messageToTransmit)
Message to transmit: 06729020860821106419048530205105224040360495103025
# back to session 2, let's prepare for receiving the message
>>> charStr = s3.recvfrom(1024) # <= this will block
# back to session 1 to send a message
# you do not share what (studentIP,iUDPPortStudent), but from
# what you describe it is not ('127.0.0.1', 60911), let's say
# studentIP = 'localhost' and iUDPPortStudent = 50001
>>> studentIP = 'localhost'
>>> iUDPPortStudent = 50001
# now let send a message that will be sent successfully but not received, i.e.,
# it will not unblock recvfrom in session 2
>>> s3.sendto(messageToTransmit.encode(),(studentIP,iUDPPortStudent))
50
# ... but if try to send to the listening endpoint it will get received
>>> s3.sendto(messageToTransmit.encode(), addr)
50
# back to session 2, to check things
>>> charStr
(b'06729020860821106419048530205105224040360495103025', ('127.0.0.1', 50000)) # <= SUCCESS
There are two ways to fix this. The one shown above which involves changing the server code, which essentially involves what is shown above, i.e., send the message to a listening endpoint by modifying the address passed to s3.sendto. If I understand things correctly, this is not an option as you are trying to write the client code. The second way is to send the message to (studentIP, iUDPPortStudent), but have a listening endpoint at the other end. If studentIP and iUDPPortStudent are known to your "client" program, which I assume is the case, you can add code similar to what you have at the top of the server program code snippet.
Specifically, add in place of charStr = s3.recvfrom(1024) something like:
addr = (studentIP, iUDPPortStudent)
s4 = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s4.bind(addr)
charStr = s4.recvfrom(1024) # <= this will block and unblock when you send the message using s3.sendto(messageToTransmit.encode(),(studentIP,iUDPPortStudent))
For completeness, you will need to change localhost to 'localhost' and if in your experiments you encounter a OSError: [Errno 98] Address already in use you will have to wait for the TIME-WAIT period to pass or set the SO_REUSEADDR flag by adding s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) before bind.

Server unable to sort integer array and send to client

I'm trying to send random size int array from multiple-clients to server which will keep adding the newly received int array to a global array and return accumulated sorted array to client. My client code is able to send and receive int array to/from server. But server is not able to read the int array and sort and send back to client (My server can just read and send back original int array to client, but it's not what I want).
In my server code, commented part is not working. I am very new in python and socket programming.
Client.py
# Import socket module
import socket, pickle
import random
def Main():
# local host IP '127.0.0.1'
host = '127.0.0.1'
# Define the port on which you want to connect
port = 12345
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# connect to server on local computer
s.connect((host, port))
while True:
# Generate Random array to be sent to server
arr = []
# Generate random size between 10 and 20
# random_size = random.randint(10, 20)
random_size = random.randint(1, 3)
for i in range(0, random_size):
arr.append(random.randint(0, 10))
print('Array = ' + str(arr))
# Serialise the array to byte stream before sending to server
data_stream = pickle.dumps(arr)
#Array byte stream sent to server
s.send(data_stream)
# messaga received from server
data = s.recv(1024)
#deserialise the byte stream into array after receiving from server
data_arr = pickle.loads(data)
# print the received message
#print('Received', repr(data_arr))
print('Received from Server: ', data_arr)
# ask the client whether he wants to continue
ans = input('\nDo you want to continue(y/n) :')
if ans == 'y':
continue
else:
break
# close the connection
s.close()
if __name__ == '__main__':
Main()
Server.py
# import socket programming library
import socket, pickle
# import thread module
from _thread import *
import threading
from sortedcontainers import SortedList
import bisect
#Container to store accumulated int array from multiple clients
sl = SortedList()
# To protect
print_lock = threading.Lock()
# thread fuction
def threaded(c):
while True:
# data received from client
data = c.recv(1024)
# Data from client can't be printed =============== why?
print(data)
if not data:
print('No data received from client - Bye')
# lock released on exit
print_lock.release()
break
c.send(data) # ===> It works but I want to add received int array into global sl before sending back to client
'''
////////////////////// Code in this comment section is not working //////////////////
#Deserialise Byte stream array from client into array list
data_arr = pickle.loads(data)
#Add received int array from client to global sortedList sl in sorted order
for i in data_arr:
bisect.insort(sl, i)
sl.add(i)
print(sl)
#Serialise sorted sl into Byte stream before sending to client
data_stream = pickle.dumps(sl)
# send back sorted integer list to client
c.send(data_stream)
'''
# connection will never be closed, server will run always
#c.close()
def Main():
host = ""
# We can use a port on our specific computer
# But in this case it is 12345 (it can be anything)
port = 12345
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((host, port))
print("socket binded to post", port)
# put the socket into listening mode
s.listen(5)
print("socket is listening")
# a forever loop until client wants to exit
while True:
# establish connection with client
c, addr = s.accept()
# lock acquired by client
print_lock.acquire()
print('Connected to :', addr[0], ':', addr[1])
# Start a new thread and return its identifier
start_new_thread(threaded, (c,))
s.close()
if __name__ == '__main__':
Main()
I run it in terminal and I see error
NotImplementedError: use ``sl.add(value)`` instead
but it seems to be incomplete message.
After removing
bisect.insort(sl, i)
it starts working.
Probably there was: use ``sl.add(value)`` instead of ``bisect.insort(sl, i)``

Categories