Implement UDP with TCP features - python

I'm not sure where to even start, so far I have this for the server side:
# Server program
from socket import *
import time
import sys
serverhost = '127.0.0.1'
serverport = 5005
buffersize = 2048
serversock = socket(AF_INET,SOCK_DGRAM)
serveraddr = (serverhost, serverport)
serversock.bind(serveraddr)
print 'Server is ready to receive'
while True:
try:
message, clientaddr = serversock.recvfrom(buffersize)
print 'Server received ', message, 'from ', str(clientaddr)
print "Server sending back " + str(message)
serversock.sendto(message, clientaddr)
except:
print 'Exception occured, closing socket'
break
serversock.close()
and this for the client side:
# Client program
from socket import *
import time
import sys
import struct
def Main():
srcip = destip = "127.0.0.1"
srcport, destport = 5005, 5000
payload = '[TESTING]\n'
tcp = make_tcp(srcport, destport, payload)
packet = tcp + payload
buffersize = 2048
addr = (destport, serverport)
clientsock = socket(AF_INET,SOCK_DGRAM)
def tcp(srcport,destport, payload, seq=123 , ackseq=0,
fin=False, syn=True, rst=False, psh=False, ack=False, urg=False,
window = 5840):
offsetres = (5 << 4) | 0
flags = (fin | (syn << 1) | (rst << 2) |
(psh << 3) | (ack << 4) | (urg << 5))
return struct.pack('HHLLBBHHH',
srcport, destport, seq, ackseq, offset_res,
flags, window, 0, 0)
data = "This is the client"
try:
start = time.time()
clientsock.sendto(data, packet, serveraddr, (destip, 0))
print "Client sent message ...", data, "... waiting for response."
response, addr = clientsock.recvfrom(buffersize)
response_id = struct.unpack('!HI', response[4:6])
end = time.time()
elapsed = end - start
print response_id
print "Elapsed time = ", elapsed
except:
print "Exception occured"
clientsock.close()
if __name__== "__main__":
Main()
I'm not sure if the TCP header is correct so far, but How do I start a message exchange? It's supposed to be sending packets over UDP with TCP features. How should I start the connection (three way handshake)?

Related

socket.recv() is not firing on sending side

I am creating a very simple rdt 2.2 socket program that transfers an image file dictated as "Cat.bmp" from client to server. Once the client reads the first line of data from the bmp file, it sends it to the server, and then the server will continue to repeat reading this same line in an infinite loop. I have no idea why this won't allow the client to send new data. Any suggestions on how to fix this would be very appreciated.
Client.py
import binascii
import struct
import sys
import hashlib
import base64
import time
from asyncio.tasks import sleep
def rdtSend(currentSequence , currentAck , data):
values = (currentACK, currentSequence, data)
UDPData = struct.Struct('I I 8s')
packedData = UDPData.pack(*values)
checksumVal = hashlib.md5(packedData).hexdigest().encode('utf-8')
sendPacket = makepacket(currentACK, currentSequence, data, checksumVal)
UDPSend(sendPacket)
def makepacket(currentACK, currentSequence, data, checksumVal):
values = (currentACK, currentSequence, data, checksumVal)
packetData = struct.Struct('I I 8s 32s')
packet = packetData.pack(*values)
return packet
def UDPSend(sendPacket):
senderSocket.sendto(sendPacket, (IP, Port))
def dataError(receivePacket):
checksum = makeChecksum(receivePacket[0], receivePacket[1], receivePacket[2])
# Compare calculated chechsum with checksum value in packet
if receivePacket[3] == checksum:
print('CheckSums is OK')
return False
else:
print('CheckSums Do Not Match')
return True
def makeChecksum(ACK, SEQ, DATA):
values = (ACK, SEQ, DATA)
packer = struct.Struct('I I 8s')
packedData = packer.pack(*values)
checksum = hashlib.md5(packedData).hexdigest().encode('utf-8')
return checksum
def isACK(receivePacket, ACKVal):
if (receivePacket[0] == ACKVal):
return True
else:
return False
IP = "127.0.0.1"
#Local Port for client and server
Port = 20001
#buffer to receive information from client
bufferSize = 1024
unpacker = struct.Struct('I I 8s 32s')
senderSocket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
senderSocket.connect((IP , Port))
print("UDP IP:", IP)
print("UDP port:", Port)
filename = 'Cat.bmp'
file = open(filename , 'rb')
# current data item being processed
data = file.read(bufferSize)
currentSequence = 0
currentACK = 0
while (data):
rdtSend(currentSequence, currentACK , data)
packet, addr = senderSocket.recvfrom(bufferSize)
print(packet)
print("Received from: ", addr)
receivePacket = unpacker.unpack(packet)
if(dataError(receivePacket) == False and isACK(receivePacket , currentACK) == True):
currentACK = currentACK + 1
currentSequence = (currentSequence + 1) % 2
data = file.read(bufferSize)
print("sending more data")
else:
print("Resending packet")
file.close()
senderSocket.close
Server.py
import socket
import binascii
import struct
import sys
import hashlib
import base64
import time
from asyncio.tasks import sleep
def rdtSend(currentSequence , currentAck , data):
values = (currentACK, currentSequence, data)
UDPData = struct.Struct('I I 8s')
packedData = UDPData.pack(*values)
checksumVal = hashlib.md5(packedData).hexdigest().encode('utf-8')
#This is where it gets the UDP packet
sendPacket = makepacket(currentACK, currentSequence, data, checksumVal)
UDPSend(sendPacket)
def makepacket(currentACK, currentSequence, data, checksumVal):
values = (currentACK, currentSequence, data, checksumVal)
packetData = struct.Struct('I I 8s 32s')
packet = packetData.pack(*values)
return packet
def UDPSend(sendPacket):
receiverSocket.sendto(sendPacket, (IP, Port))
def makeChecksum(ACK, SEQ, DATA):
values = (ACK, SEQ, DATA)
packer = struct.Struct('I I 8s')
packedData = packer.pack(*values)
checksum = hashlib.md5(packedData).hexdigest().encode('utf-8')
return checksum
#Function that checks the packet for corruption
def dataError(receivePacket):
# Calculate new checksum of the [ ACK, SEQ, DATA ]
checksum = makeChecksum(receivePacket[0], receivePacket[1], receivePacket[2])
# Compare calculated chechsum with checksum value in packet
if receivePacket[3] == checksum:
print('CheckSums is OK')
return False
else:
print('CheckSums Do Not Match')
return True
#IP Address for local communications
IP = "127.0.0.1"
#Local Port for client and server
Port = 20001
#buffer to receive information from client
bufferSize = 1024
# Integer, Integer, 8 letter char array, 32 letter char array
unpacker = struct.Struct('I I 8s 32s')
# Create the actual UDP socket for the server
receiverSocket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
# Bind the socket to the local IP address and port
receiverSocket.bind((IP, Port))
currentACK = 0
currentSequence = 0
dataFile = open('receive.bmp' , 'wb')
print("Listening")
packet, addr = receiverSocket.recvfrom(bufferSize)
receivedPacket = unpacker.unpack(packet)
#Where the previous functions are used to send the packets back to the client
while receivedPacket[2]:
print("Received from:", addr)
print("Data Received:" , receivedPacket[2])
#This compares checksums to see if there are errors
if not dataError(receivedPacket):
dataFile.write(receivedPacket[2])
# Built checksum [ACK, SEQ, DATA]
ACK = receivedPacket[0]
SEQ = receivedPacket[1]
DATA = b''
print('Packeting')
rdtSend(currentSequence , currentACK , DATA)
print('Sent')
currentACK = currentACK + 1
currentSequence = (currentSequence + 1) % 2
packet, addr = receiverSocket.recvfrom(bufferSize)
receivedPacket = unpacker.unpack(packet)
else:
print('Packet error')
checksumVal = makeChecksum(packet[0] + 1, (packet[1] + 1) % 2, b'')
packet = makepacket(packet[0] + 1, (packet[1] + 1) % 2, b'', checksumVal)
print('Packeting')
receiverSocket.sendto(packet, addr)
print('Sent')
packet, addr = receiverSocket.recvfrom(bufferSize)
receivedPacket = unpacker.unpack(packet)
dataFile.close()
receiverSocket.close```

Sending pictures on Socket Python

I'm currently working on a project and I need to send a photo to another computer through Python. I'm using the module Socket but when I tried to send my photo, I got an error saying "A message sent to a datagram socket was larger than the internal message buffer or another network boundary, or the buffer used to receive a datagram was smaller than the datagram itself"
How can I fix that ?
Thanks
Your image is too big to be sent in one UDP packet. You need to split the image data into several packets that are sent individually.
socket.SOCK_STREAM instead of socket.SOCK_DGRAM. There you don't have to worry about packet sizes and ordering. Although you need to set buffer_size.
import random
import socket, select
from time import gmtime, strftime
from random import randint
imgcounter = 1
basename = "image%s.png"
HOST = '127.0.0.1'
PORT = 6666
connected_clients_sockets = []
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)
connected_clients_sockets.append(server_socket)
buffer_size = 4096
while True:
read_sockets, write_sockets, error_sockets = select.select(connected_clients_sockets, [], [])
for sock in read_sockets:
if sock == server_socket:
sockfd, client_address = server_socket.accept()
connected_clients_sockets.append(sockfd)
else:
try:
print ' Buffer size is %s' % buffer_size
data = sock.recv(buffer_size)
txt = str(data)
if txt.startswith('SIZE'):
tmp = txt.split()
size = int(tmp[1])
print 'got size'
print 'size is %s' % size
sock.send("GOT SIZE")
# Now set the buffer size for the image
buffer_size = 40960000
elif txt.startswith('BYE'):
sock.shutdown()
elif data:
myfile = open(basename % imgcounter, 'wb')
# data = sock.recv(buffer_size)
if not data:
myfile.close()
break
myfile.write(data)
myfile.close()
sock.send("GOT IMAGE")
buffer_size = 4096
sock.shutdown()
except:
sock.close()
connected_clients_sockets.remove(sock)
continue
imgcounter += 1
server_socket.close()
Server code:
import socket
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_socket.bind(("", 5005))
server_socket.listen(5)
import os
client_socket, address = server_socket.accept()
print "Conencted to - ",address,"\n"
while (1):
choice = client_socket.recv(1024)
choice = int(choice)
if(choice == 1):
data = client_socket.recv(1024)
print "The following data was received - ",data
print "Opening file - ",data
fp = open(data,'rb')
strng = fp.read()
size = os.path.getsize(data)
size = str(size)
client_socket.send(size)
client_socket.send (strng)
#client_socket.close()
if (choice == 2 or choice == 3):
data = client_socket.recv(1024)
print "The following data was received - ",data
print "Opening file - ",data
img = open(data,'rb')
while True:
strng = img.read(512)
if not strng:
break
client_socket.send(strng)
img.close()
print "Data sent successfully"
exit()
Client Code:
Please refer to https://docs.python.org/2/library/socket.html#socket.socket.setblocking
This code will be paused until it receives data. As default all sockets are in blocking mode. You should make it non-blocking.
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, an error exception
is raised; in blocking mode, the calls block until they can proceed.
s.setblocking(0) is equivalent to s.settimeout(0.0); s.setblocking(1)
is equivalent to s.settimeout(None).
Or:
put client_socket.settimeout(10.0) after while(1) and before client_socket.send(k)
write after while(1) -> c,a = client_socket.accept()
c.settimeout(10.0) -> then after that anywhere there is client_socket change it to "c"
Therefore:
client_socket.connect(("", 5005))
deadline = time.time() + 20.0
client_socket.settimeout(deadline - time.time())
#or
client_socket.setblocking(0)
All Code:
import socket,os
client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client_socket.connect(("", 5005))
client_socket.settimeout(1.0)
k = ' '
size = 1024
while(1):
print "Do you want to transfer a \n1.Text File\n2.Image\n3.Video\n"
k = raw_input()
client_socket.send(k)
k = int (k)
if(k == 1):
print "Enter file name\n"
strng = raw_input()
client_socket.send(strng)
size = client_socket.recv(1024)
size = int(size)
print "The file size is - ",size," bytes"
size = size*2
strng = client_socket.recv(size)
print "\nThe contents of that file - "
print strng
if (k==2 or k==3):
print "Enter file name of the image with extentsion (example: filename.jpg,filename.png or if a video file then filename.mpg etc) - "
fname = raw_input()
client_socket.send(fname)
fname = 'documents/'+fname
fp = open(fname,'w')
while True:
try:
strng = client_socket.recv(512)
if not strng:
break
except timeout:
continue
fp.write(strng)
fp.close()
print "Data Received successfully"
exit()

Why I have some packets lost in localhost?

I try to develop a server and a client programs in Python 2.7, which can switch in UDP or in TCP, based on this echo program :
TCP vs. UDP socket latency benchmark
For now, i just try to program it as local host
When i run it in TCP (is_UDP = False), the server program shows me that there is no packet lost (total_perdu = 0)
But if i run it in UDP (is_UDP = True), it gives me some packets lost.
This is my code for the server :
import socket
from numpy import *
server_address = ("127.0.0.1", 4444)
client_address = ("127.0.0.1", 4445)
bufferSize = 4096
# is_UDP = True
is_UDP = False
# Create a datagram socket
if is_UDP == True:
UDP_Server_Socket_in = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
UDP_Server_Socket_in.bind(server_address)
UDP_Server_Socket_out = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
UDP_Server_Socket_out.connect(client_address)
connection = UDP_Server_Socket_in
print("UDP server is running...")
else :
TCP_Server_Socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
TCP_Server_Socket.bind(server_address)
TCP_Server_Socket.listen(1)
connection, client_address = TCP_Server_Socket.accept()
print("TCP server is running...")
t = 0
total_perdu = 0
i = 0
while(True):
i += 1
# Receive packet from client
data_2= connection.recv(bufferSize)
tab=fromstring(data_2,dtype="int32")
size=len(data_2)
while size<bufferSize:
data_2= connection.recv(bufferSize-size)
size+=len(data_2)
if data_2:
perdu=int(tab[0])-t-1
sperdu=""
if perdu>0:
total_perdu+=perdu
sperdu = "(%d)"%(perdu)
print "Receive data : %s %d %d %s" % (tab[0], len(tab), total_perdu,sperdu)
t=int(tab[0])
And this is my code for the client:
import socket
from numpy import *
import time
server_address = ("127.0.0.1", 4444)
client_address = ("127.0.0.1", 4445)
# Packets variables
packet_size = 1024
total_packet = 1000
bufferSize = 4*packet_size
# Variables initialization
error = 0
total_throughput = 0
total_latene = 0
total_ratio = 0
total_stop_time_1 = 0
total_stop_time_3 = 0
# Creation of a packet
send_tab = zeros(packet_size, int)
for i in range(0, packet_size):
send_tab[i] = i
data_size = (send_tab.size+8)*send_tab.itemsize
print "Data size : %d" % data_size
print "Tab : %s \n" % send_tab
# is_UDP = True
is_UDP = False
# Create a socket at client side
if is_UDP == True:
UDP_Client_Socket_out = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
UDP_Client_Socket_out.connect(server_address)
UDP_Client_Socket_in = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
UDP_Client_Socket_in.bind(client_address)
connection = UDP_Client_Socket_out
print("UDP client is running...")
else:
TCP_Client_Socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
TCP_Client_Socket.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 0)
TCP_Client_Socket.connect(server_address)
connection = TCP_Client_Socket
print("TCP client is running...")
start_time_0 = time.clock()
for packet_number in range(0,total_packet):
send_tab[0] = packet_number
# Send packet to server
start_time=time.clock()
sent = connection.send(send_tab)
if sent:
stop_time_1 = time.clock() - start_time
# Calculate throughput and ratio
throughput = data_size / (stop_time_1 * 1000000)
print "stop_time_1 \t%f" % stop_time_1
total_throughput += throughput
stop_time_3 = (time.clock() - start_time_0)
print "Results : \n"
print " Packet error : %d \n" % error
print " Thoughput: %f Mo/s \n " % (total_throughput/total_packet)
print " total_stop_time_1 : %f s \n " % (total_stop_time_1/total_packet)
print " stop_time_3 : %f \n" % stop_time_3
So, I have 3 questions about it :
Is it normal to have some packets which are lost even if I do it as a local host?
If yes, why?
Will I have the same problem if I program it in C?
From your code it looks like you expect to receive the UDP packets in the same order you are sending them. I don't think you are loosing packets, but rather the order in which they are received by the server is not the expected one (which is normal for UDP).
Also, you should take into consideration that UDP does not guarantee neither the order or the receiving of packets so your program should take this into consideration.
I would refactor the code and add the tab into a list, then sort it and check for the gaps (at the end of transmission).
Another way would be to send a reply from the server and make the check on the client (but this might increase the number if you deploy it on the Internet).

Unable to get Socket to receive packets

I'm trying to send a message from Client to Server using socket. For some reason, the message is not received. example: the client sends 'myname_0' the server needs to receive it and decode it and continue further.
Listener:
import socket
class SocketSender():
def __init__(self):
self.sock = socket.socket()
ip = socket.gethostname() # IP to server.
port = 7000
self.sock.bind((ip, port))
print("Binding successful.")
self.sock.listen(2)
print("Listening....")
self.listening = True
# self.sock.connect((ip, port))
# print("Connected.")
def sendpacket(self, packet):
self.sock.send(packet.encode())
def receivepacket(self):
while self.listening:
con, addr = self.sock.accept()
print("Receiving packet from " + str(addr))
packet = self.sock.recv(1024).decode("utf-8")
return str(packet)
Sender:
import socket
sock = socket.socket()
ip = socket.gethostname()
port = 7000
sock.connect((ip, port))
print("connection to " + ip)
message = "test_0"
sock.send(message.encode("utf-8"))
When run:
import GUI
import SocketSender
# Entry: 0, Exit: 1
gui = GUI.ASGui()
# gui.run()
socket = SocketSender.SocketSender()
id = input()
while 1 == 1:
packet = socket.receivepacket()
name, state = packet.split("_")
break
if state == 0:
print("Welcome back, " + name)
else:
if state == 1:
print("Goodbye, " + name)
I do get the outputs Listening and Binded. But I am unable to receive a message. Help would be appreciated. Thank you.

Bad data being received

I am writing a client and server app in Python and I have a problem with received data. In the first "loop" I received good data but in the next "loop" I received bad data. What do I have to do? Maybe you have a better idea to send and receive data.
This is Client:
import socket
import pickle
import sys
host = socket.gethostname()
port = 2004
BUFFER_SIZE = 100000
print("What you want to do:\r1. Select from base\r2.Insert into base")
MESSAGE, MESSAGE1 = input("tcpClientA: Enter message/ Enter exit:").split(",")
tcpClientA = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
tcpClientA.connect((host, port))
while MESSAGE != 'exit':
tcpClientA.send(MESSAGE.encode())
tcpClientA.send(MESSAGE1.encode())
lista=pickle.loads(tcpClientA.recv(BUFFER_SIZE).strip())
print(lista)
print("Variables 1 and 2 are: ", MESSAGE, MESSAGE1)
MESSAGE, MESSAGE1 = input("tcpClientA: Enter message to continue/ Enter exit:").split(",")
tcpClientA.close()
This is Server:
import socket
from threading import Thread
import pyodbc
import pickle
# Multithreaded Python server : TCP Server Socket Thread Pool
class ClientThread(Thread):
def __init__(self,ip,port):
Thread.__init__(self)
self.ip = ip
self.port = port
print ("[+] New server socket thread started for " + ip + ":" + str(port) )
def run(self):
while True :
connsql = pyodbc.connect('DRIVER={SQL Server};SERVER=I7-KOMPUTER\SQLEXPRESS;DATABASE=test')
cursor = connsql.cursor()
data = conn.recv(2048)
#datasplitx, datasplity = data.decode().split(",", 1)
try:
xy = []
xy = data.decode().split(" ")
print("dat: ",data.decode())
print("After del:",xy)
x=str(xy[0])
#y=str(xy[1])
#x, y = [str(x) for x in data.decode().split()]
#y=str(datasplit[1])
#x = str(datasplit[0])
#y = str(datasplit[1])
except ValueError:
print("List does not contain value")
print ("Server received data:", xy)
if x == 'exit':
break
if x == '1':
#if data.decode() == '1':
cursor.execute("select rtrim(name) from client")
rows = cursor.fetchall()
zap=pickle.dumps(rows)
conn.send(zap)
print(pickle.loads(zap))
if x == '2':
#if data.decode() == '2':
cursor.execute("insert into dbo.klient values('"+y+"')")
connsql.commit()
zro=pickle.dumps("Done.")
conn.send(zro)
del xy[:]
print ("cleared list: xy",xy)
# Multithreaded Python server : TCP Server Socket Program Stub
TCP_IP = '0.0.0.0'
TCP_PORT = 2004
BUFFER_SIZE = 1024 # Usually 1024, but we need quick response
tcpServer = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
tcpServer.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
tcpServer.bind((TCP_IP, TCP_PORT))
threads = []
while True:
tcpServer.listen(4)
print ("Multithreaded Python server : Waiting for connections from TCP clients...\r" )
(conn, (ip,port)) = tcpServer.accept()
newthread = ClientThread(ip,port)
newthread.start()
threads.append(newthread)
print("Client IP: " +str(ip))
for t in threads:
t.join()

Categories

Resources