This question already has an answer here:
Extract received data in a tcp socket in Python
(1 answer)
Closed 7 years ago.
I am trying to send a custom packet (with a custom layer) using Scapy in python socket.
Here's the code of the client
#!/usr/bin/env python
import socket
from scapy.all import *
TCP_PORT = 5000
BUFFER_SIZE = 1024
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('192.168.240.1', TCP_PORT))
class Reservation(Packet):
name = "ReservationPacket"
fields_desc=[ ByteField("id", 0),
BitField("type",None, 0),
X3BytesField("update", 0),
ByteField("rssiap", 0)]
k = IP(dst="192.168.240.1")/Reservation()
k.show()
send(k)
print "Reservation Message Sent"
s.close()
and the packet k appears to be successfully created and sent.
Here's the server which is responsible to receive the packet:
#!/usr/bin/python
import socket
from scapy.all import *
class Reservation(Packet):
name = "ReservationPacket"
fields_desc=[ ByteField("id", 0),
BitField("type",None, 0),
X3BytesField("update", 0),
ByteField("rssiap", 0)]
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.bind(('192.168.240.1', 5000))
s.listen(1)
while True :
conn, addr = s.accept()
print 'Connection address:', addr
print ''
data = conn.recv(1024)
data.show()
conn.close
s.close()
and this is the output I get from the server:
Connection address: ('192.168.240.5', 58454)
Traceback (most recent call last):
File "server.py", line 36, in <module>
data.show()
AttributeError: 'str' object has no attribute 'show'
How can I receive my packet and decode it to read its custom layer?
Data became a string in this line:
data = conn.recv(1024)
Checking the doc https://docs.python.org/2/library/socket.html
socket.recv(bufsize[, flags]) Receive data from the socket. The
return value is a string representing the data received. The maximum
amount of data to be received at once is specified by bufsize. See the
Unix manual page recv(2) for the meaning of the optional argument
flags; it defaults to zero.
What are you trying to do with data.show(), you just could print the data with:
print data
Also follow this link to decode the string:
Python - converting sock.recv to string
stringdata = data.decode('utf-8')
Related
I am experimenting with import sockets in python and I have a client.py and a server.py and when server.py receives a message from client.py I get this error
Traceback (most recent call last):
File "C:/Users/Owner/PycharmProjects/pythonProject/echo_server.py", line 13, in <module>
data = conn.recv(1024)
ConnectionAbortedError: [WinError 10053] An established connection was aborted by the software in your host machine
My full code is:
import socket
host = ''
port = 12345
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((host, port))
print(host , port)
s.listen(1)
conn, addr = s.accept()
print('Connected by', addr)
while True:
data = conn.recv(1024)
data = str(data)
if not data: break
print("Client Says: "+data)
conn.sendall(b"Server Says:Message Received")
input(">")
conn.close()
Can someone tell me what this error is and what I can do to fix it?
The if statement if not data is equivalent to writing if data != "", while the empty string your server receives is b''. You have several options to fix it.
data = conn.recv(1024).decode() is the proper way to allocate the data sent by the client. You can now print(data) or compare data to an empty string.
If you still don't want to decode() your message you could change your if statement to if data != b'' or if data is not None.
Update
If it wasn't clear, your str(data) conversion causes the if statement to work unproperly, which is set to False without allowing you to break when a client disconnects.
I know that similar questions have been raised but they don't seem to work for me! I have tried serializing the dictionary then converting that to a string then encoding it before I send it over the socket. No success so far!
This is my server code:
#library
import socket
import pickle
#socket initialization
host = "127.0.0.1"
port = 5000
mainAddr = (host, port)
#dict initialization
dataDict = {} #just imagine that dict has content
#create socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) #TCP
s.bind((mainAddr))
s.listen(4)
print('program started')
print('listening..')
while True:
try:
conn, addr = s.accept()
print("connection from: "+str(addr))
print("sending message..")
pickle.dumps(dataDict)
print('pickled!')
dataS = str(dataP)
print('stringed!')
dataE = dataS.encode('UTF-8')
print('encoded!')
s.sendto(dataE,addr)
print('data sent!')
except:
pass
s.close()
For the socket initialization, I've tried other types:
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) #UDP
s = socket.socket()
For the sending part, I've tried these alternatives:
s.send(dataE)
s.send(dataE,addr)
s.sendall(dataE)
s.sendall(dataE,addr)
When I run the program, these get printed out:
program started
listening..
connection from:<insert addr here>
sending message..
pickled!
stringed!
encoded!
Only data sent! is not sent. So I am guessing that it's the sending part that has a problem.
For the client side, here's the code:
#library
import socket
import pickle
#initialization
host = '127.0.0.1'
port = 5000
buffer = 1024
#create socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) #TCP
s.connect((host,port))
print('connected!')
#receive dictionary
print('receiving message..')
while True:
data, addr = s.recvfrom(buffer)
print('received!')
dataD = data.decode("UTF-8")
print('decoded!')
dataP = pickle.loads(dataD)
print('unpickled!')
print(str(dataP))
s.close()
In the client terminal, only the following prints:
connected!
receiving message..
On the client side, I've tried changing the order of unpickling and decoding but still, to no avail.
A TCP server socket is not actually used for sending/receiving data; I'm surprised you're not getting an error when calling s.send() or similar on it. Instead, it's a factory for producing individual sockets for each client that connects to the server - conn, in your code. So, conn.sendall() is what you should be using. No address parameter is required, the individual socket already knows who it is talking to. (.send() is unreliable without some extra work on your part; .sendto() is only used with UDP sockets that have not been connected to a particular client.)
I'm making a simple Python application which will allow people to communicate with each other through a CLI. I am relatively new to the sockets module, however my code has no problems. Except for one. When I run my two scripts (chatclient.py and chatserver.py), they run fine. The server starts up, and the client will ask the user for their name and the message. However upon clicking enter to send the message, i receive:
TypeError: decoding str not supported
I have tried using .encode('utf-8)/ .decode('utf-8') but still the same error. The code will be below (with multi comments around the 'wrong' code).
#client.py
import socket
import threading
import time
tLock = threading.Lock() #creates a lock for the thread and prevents output to the screen
shutdown = False
def receiving(name, sock):
while not shutdown: #while the program is still running
try:
tLock.acquire() #acquires the lock
while True:
data, addr = sock.recv(1024).decode('utf-8') #gets the data and address from the data received
print(str(data))
except:
pass
finally:
tLock.release() #releases the lock
host = "127.0.0.1" #uses localhost as the host
port = 0 #picks up any free port on the computer
server = ("127.0.0.1",5000)
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.bind((host, port))
s.setblocking(0)
rt = threading.Thread(target=receiving, args=("RecvThread", s))
rt.start()
'''name = input("Enter your name: ")
message = input("> ")
while message != "q":
if message != '':
print("From ",name)
s.sendto(str(name, message), (host,port)).decode('utf-8')'''
tLock.acquire()
message = input('')
tLock.release()
time.sleep(0.5)
shutdown = True
rt.join()
s.close()
^^^client
#server.py
import socket
import time
host = "127.0.0.1" #makes localhost the host server
port = 5000 #uses any random port between 1024 and 65535
clients = []
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) #creates a new socket object
s.bind((host,port)) #binds the host and port to socket object
s.setblocking(0) #sets the blocking to 0 (essentially no blocking)
quitting = False
print("The server has now started on ",time.ctime(time.time()))
while not quitting: #while quitting hasn't happened
try:
data, addr = s.recvfrom(1024).decode('utf-8') #tries to get data and address from the data coming in
if "Quit" in data: #if the data has quit in it
quitting = True #quitting = true meaning the while not quitting loop would break
if addr not in clients: #if the address given is not in the list 'Clients'
clients.append(addr) #then it will append it to the list
print(time.ctime(time.time()),"- ",str(addr).decode('utf-8')," : ",str(data).decode('utf-8')) #prints the time, the address and the message
for client in clients: #for each client in the list of clients
s.sendto(bytes(data, 'utf-8')) #send the data to the clients
s.sendto(bytes(client, 'utf-8'))
except:
pass
s.close()
^^^server
If you pass 2 or more values to str, it tries to decode, but in your case, the first argument is already string object (because the return value of input function is string); causes the error.
>>> str('a')
'a'
>>> str('a', 'utf-8') # trying to decode (the 2nd arg. is encoding)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: decoding str is not supported
>>> str(b'a', 'utf-8')
'a'
Beside that, you need to pass bytes object to socket.sendto as the first argument. Encode string to get a bytes object:
>>> 'a'.encode() # You can omit encoding arg.; `utf-8` is default in Python 3.x
b'a'
>>> 'a'.encode('utf-8')
b'a'
Replace following line of client code:
s.sendto(str(name, message), (host,port)).decode('utf-8')
with:
s.sendto('{}: {}'.format(name, message).encode('utf-8'), (host,port))
data, addr = s.recvfrom(1024).decode('utf-8')
Above line is also wrong. socket.recvfrom(..) returns a tuple of (message, address). The tuple does not have decode method. You need to decode message only.
data, addr = s.recvfrom(1024)
data = data.decode('utf-8')
server
import socket
import time
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.bind(('127.0.0.1', 5000))
print("The server has now started on ", time.ctime())
clients = []
while True:
data, addr = s.recvfrom(1024)
text = data.decode('utf-8')
if "Quit" in text:
break
if addr not in clients:
clients.append(addr)
print(time.ctime(), "-", addr, ":", text)
for client in clients:
s.sendto(data, client)
s.close()
I have created two scripts which establish a client socket and server socket in localhost.
Server socket
import socket
from time import ctime
HOST = ''
PORT = 21567
BUFSIZ = 1024
ADDR = (HOST,PORT)
tcpsersoc = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
tcpsersoc.bind(ADDR)
tcpsersoc.listen(5)
while True:
print('waiting for connection .... ')
print(ADDR)
tcpClisoc,addr = tcpsersoc.accept()
print('......connected from', addr)
while True:
data = tcpClisoc.recv(BUFSIZ)
if not data:
break
tcpClisoc.send('[%s]%s'%(bytes(ctime(),'UTF-8'),data))
tcpClisoc.close()
tcpsersoc.close()
Client socket
from socket import *
HOST= '127.0.0.1'
PORT = 21567
BUFSIZ = 1024
ADDR = (HOST,PORT)
tcpCliSock = socket(AF_INET,SOCK_STREAM)
tcpCliSock.connect(ADDR)
while True:
data = input('>')
if not data:
break
tcpCliSock.send(data.encode('utf-8'))
data = tcpCliSock.recv(BUFSIZ)
if not data:
break
print(data.decode('utf-8'))
tcpCliSock.close()
I'm still getting the below error despite converting the data into a bytes object. I'm using python 3.x
this is the error raised by the server socket
waiting for connection ....
('', 21567)
......connected from ('127.0.0.1', 52859)
Traceback (most recent call last):
File "<pyshell#9>", line 1, in <module>
import exampletcpserver
File "C:/Python34\exampletcpserver.py", line 23, in <module>
tcpClisoc.send('[%s]%s'%(bytes(ctime(),'UTF-8'),data))
TypeError: 'str' does not support the buffer interface
Please let me know where i'm going wrong.
You are trying to send a string, but sockets require you to send bytes. Use
tcpClisoc.send(('[%s]%s' % (ctime(), data.decode("UTF-8"))).encode("UTF-8"))
Python 3.5 will support the alternative
tcpClisoc.send(b'[%s]%s' % (bytes(ctime(), 'UTF-8'), data))
I am trying to create a basic instant message program that uses a p2p (peer-to-peer) connection so it will not need a server. I am pretty sure nothing is wrong, but every time I run the client program I have created, I get this error:
s.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)
NameError: global name 'SOL_SOCKET' is not defined
Here is the program:
import socket
def Receiver():
# Create socket that supports IPv4, TCP Protocol
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
print "Socket created."
# Requests for IP of host (DNS)
dns = "localhost"
HOST = ''
PORT = 25395
try:
s.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)
except socket.error as serror:
print "socket error"
s.bind((HOST, PORT)) # Listens on all interfaces...
print 'Listening on port 25565'
s.listen(True) # Listen on the newly created socket...
conn, addr = s.accept()
print 'Connected in port 25565'
data = conn.recv(1024)
print data
s.close()
def Sender():
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
dns = "localhost"
HOST = socket.gethostbyname(dns)
port = 25565
# Connect to server
s.connect((host,port))
print "Socket connected to " + dns + " on IP " + host
# Assign message to be sent to server to a variable
message = raw_input("Message to be sent to server: ")
#Send the actual message to server
s.sendall(message)
print "Message sent successfully"
s.close()
input = raw_input('S is send, R is receive: ')
if input == 's':
Sender()
if input == 'r':
Receiver()
I have tried removing s.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1) but it tells me that I cannot use 2 sockets on the same port when there isn't 2 sockets using the same port.
In your code:
s.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)
do like:
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
# ^^^^ added ^^^
because you imported just socket, check following code pieces:
>>> import socket
>>> SOL_SOCKET
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'SOL_SOCKET' is not defined
>>> socket.SOL_SOCKET
1