Python-Micropython TCP sockets on w5100s-EVB-Pico - python

I have a W5100S-EVB-Pico which is basically a Pi Pico with an ethernet port. I would like to send commands to it over a TCP socket connection. Basically I want to control hardware over ethernet using this board.
The W5100 board should be a server that accepts connections/commands.
I plan on programming a GUI in Python to send commands
I'm running this micropython version on it.
Python version 3.7
But this is the problem now: The code below keeps giving me this error: 'OSError: [Errno 107] ENOTCONN'
EDIT_01: It seems like I'm closing the connection too soon from the client side ()
EDIT_02: Do I need some kind of acknowledgement from the server before closing? Or, what are possible ways to implement this kind of communication?
Thanks for reading!
Here's the code and an explanation of what's going on:
The code on the W5100-EVB-Pico:
from machine import Pin, SPI
import network
import usocket as socket
# Only needed for static IP setup:
ip_address = '192.168.1.20'
subnet = '255.255.255.0'
gateway = '192.168.1.1'
dns = '8.8.8.8'
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
socket_port = 8080
# Init ethernet
def init_ethernet():
spi = SPI(0, 2_000_000, mosi=Pin(19), miso=Pin(16), sck=Pin(18))
nic = network.WIZNET5K(spi, Pin(17), Pin(20))
# Static IP:
# nic.ifconfig((ip_address, subnet, gateway, dns))
# DHCP:
nic.active(True)
while not nic.isconnected():
pass
ip_address = nic.ifconfig()[0]
subnet = nic.ifconfig()[1]
gateway = nic.ifconfig()[2]
dns = nic.ifconfig()[3]
print('Connected:')
print('IP ', ip_address)
print('Subnet ', subnet)
print('Gateway ', gateway)
print('DNS ', dns)
listen()
def listen():
server_socket.bind((ip_address, socket_port))
server_socket.listen(5)
print(f'Listening on {ip_address} port {socket_port}')
while True:
print('>>>This should print once and it does')
print('>>>Waiting for connection')
client, address = server_socket.accept()
print(f'Client connected from: {address}')
client.close()
if __name__ == "__main__":
init_ethernet()
The output when running this is:
netif changed 192.168.1.20
Connected:
IP 192.168.1.20
Subnet 255.255.255.0
Gateway 192.168.1.1
DNS 192.168.1.150
Listening on 192.168.1.20 port 8080
>>>This should print once and it does
>>>Waiting for connection
My Python code:
import socket
local_IP = socket.gethostbyname(socket.gethostname())
port = 8080
server_ip = '192.168.1.20'
server_port = 8080
server_address = (server_ip, server_port)
def test_socket():
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.connect(server_address)
message = 'Hello from client'
s.sendall(bytes(message, encoding="utf-8"))
if __name__ == '__main__':
test_socket()
As soon as I run this code the output from the W5100 is:
...
>>>This should print once and it does
>>>Waiting for connection
Traceback (most recent call last):
File "<stdin>", line 55, in <module>
File "<stdin>", line 37, in init_ethernet
File "<stdin>", line 49, in listen
OSError: [Errno 107] ENOTCONN
=============================================
EDIT_01:
I found that when I add 'time.sleep(1)' here:
s.sendall(bytes(message, encoding="utf-8"))
time.sleep(1)
s.close()
The error does not occur. Am I closing the socket too soon on the Python side?
=============================================
EDIT_02:
I changed this code on the server:
while True:
print('>>>Waiting for connection')
client, address = server_socket.accept()
print(f'Client connected from: {address}')
data = client.recv(1024).decode()
print(data)
client.close()
And this on the client:
def test_socket():
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(server_address)
message = 'This is a really long message of many bytes and can\n' \
'even be some very long JSON data?\n' \
'which is pretty awesome!\n' \
'Man This is what I was after !!!'
s.sendall(bytes(message, encoding="utf-8"))
time.sleep(1)
s.close()
However, time.sleep(1) is not the way to go :(
I think I should close the socket after an acknowledgement from the server?
Any hint and tips are welcome,
Thanks!

Ok, the key seems to be error catching in the communication.
This client code works like intended... for now.
import socket
import json
local_IP = socket.gethostbyname(socket.gethostname())
port = 8080
server_ip = '192.168.1.20'
server_port = 8080
server_address = (server_ip, server_port)
commands = [['A', 1, '1234567890_1234567890_1234567890'],
['B', 2, 'hello'],
['C', 3.7],
['D', 4]]
def test_socket():
for c in commands:
send(json.dumps(c))
def send(message):
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(server_address)
s.sendall(bytes(message, encoding="utf-8"))
try:
received_data, addr = s.recvfrom(128)
print(received_data, addr)
print(received_data.decode('utf-8'))
except socket.error as error:
print(f'Socket error: {error.errno}')
finally:
pass
if __name__ == '__main__':
test_socket()

Related

Python socket bind ((host, port))

im making a Reverse Shell. and in the server.py file i got this error.
i has trying in de socket_bind() s.bind((host, port))
My code:
def socket_bind():
try:
global host
global port
global s
print("Binding socket to port: " + str(port))
s.bind((host, port))
s.listen(5)
except socket.error as msg:
print("Socket binding error: " + str(msg) + "\n" + "retrying...")
socket_bind()
my error:
Binding socket to port: 90
Traceback (most recent call last):
File "c:/ReverseShell/server.py", line 50, in <module>
main()
File "c:/ReverseShell/server.py", line 47, in main
socket_bind()
File "c:/ReverseShell/server.py", line 21, in socket_bind
s.bind((host, port))
TypeError: an integer is required (got type str)
how can i fix this error?
I know where you get this code. I don't know how to fix it, but you could use the code below for server.
# first import all require module
import socket # For building tcp connection
import os # Using this module for basic operation
os.system ("clear || cls") # it clear the terminal screen
def connect ():
s = socket.socket (socket.AF_INET, socket.SOCK_STREAM) # START a socket subject s
s.bind (("192.168.0.200", 9999)) # Define IP and Port
s.listen (1) # listen METHOD for pass the parameter as 1
print ('[+] Listening for incoming TCP connection on port 8080')
conn, addr = s.accept () #I want my server to accept CLIENT AND IP ADRESS BY ACCEPT METHOD
print ('[+] We got a connection from: ', addr)# After accpeted, print out the result
ter = 'terminate'
while True: #while connection is true
command = input ("\nShell>") # Get user input and store it in command variable
if ter in command: # If we type terminate command, so close te connection and break the loop
conn.send (ter.encode('utf-8')) #to send data to client with conn.send()
conn.close ()
break
else:
conn.send(str.encode (command)) #here we will send the command to the target send commands from server to client using python socket
client = str(conn.recv(1024).decode("utf-8"))
print (client) # print the result that we got back
def main():
connect()
main ()

Getting error non-blocking (10035) error when trying to connect to server

I am trying to simply send a list from one computer to another.
I have my server set up on one computer, where the IP address is 192.168.0.101
The code for the server:
import socket
import pickle
import time
import errno
HEADERSIZE = 20
HOST = socket.gethostbyname(socket.gethostname())
PORT = 65432
print(HOST)
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((HOST, PORT))
s.listen(10)
while True:
conn, adrs = s.accept()
print(f"Connection with {adrs} has been established")
conn.setblocking(1)
try:
data = conn.recv(HEADERSIZE)
if not data:
print("connection closed")
conn.close()
break
else:
print("Received %d bytes: '%s'" % (len(data), pickle.loads(data)))
except socket.error as e:
if e.args[0] == errno.EWOULDBLOCK:
print('EWOULDBLOCK')
time.sleep(1) # short delay, no tight loops
else:
print(e)
break
The client is on another computer. The code:
import socket
import pickle
HOST = '192.168.0.101'
PORT = 65432
def send_data(list):
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.settimeout(10)
print(".")
print(s.connect_ex((HOST, PORT)))
print(".")
data = pickle.dumps(list)
print(len(data))
s.send(data)
s.close()
send_data([1,1,1])
The outputted error number of connect_ex is 10035. I read a lot about the error, but all I found was about the server side. To me, it looks like the problem is with the client and that it is unable to make a connection to 192.168.0.101. But then, I don't understand why the error I get is about non-blocking.
What is it that I am doing wrong that I am unable to send data?
First of all, how user207421 suggested, change the timeout to a longer duration.
Also, as stated here Socket Programming in Python raising error socket.error:< [Errno 10060] A connection attempt failed I was trying to run my server and connect to a private IP address.
The fix is: on the server side, in the s.bind, to leave the host part empty
HOST = ''
PORT = 65432
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((HOST, PORT))
And on the client side, use the public IP of the PC where the server is running (I got it from ip4.me)
HOST = 'THE PUBLIC IP' #not going to write it
PORT = 65432
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((host, PORT))

Python Socket Programming - ConnectionRefusedError: [WinError 10061] No connection could be made because the target machine actively refused it

I'm doing an assignment regarding socket programming in python using a client and server. I'm currently on windows 10. Before getting into the little details of the assignment, I've been trying to simply connect the server and client.
Every time I try to run the client file, I would get this error
File "tcpclient.py", line 9, in <module>
s.connect((host, port))
ConnectionRefusedError: [WinError 10061] No connection could be made because the target machine actively refused it
I have opened the firewall ports and still nothing. I've tried replacing host with '', 0.0.0.0, socket.gethostname() in both the client and server file but the error still persists. I've even tried different port numbers but it made no difference. I've tried running this code on Ubuntu and Max and I get the same error - connection refused. I've been researching for many solutions but I still have yet to find one that works. Any help would be greatly appreciated!
Note: this code was taken online but it's essentially the basis of what I need to accomplish.
tcpclient.py
import socket
host = '127.0.0.1'
port = 80
buffer_size = 1024
text = "Hello, World!"
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((host, port))
s.send(text)
data = s.recv(buffer_size)
s.close()
print("received data:", data)
tcpserver.py
import socket
host = '127.0.0.1'
port = 80
buffer_size = 20
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((host, port))
s.listen(1)
conn, addr = s.accept()
print 'Connection address:', addr
while 1:
data = conn.recv(buffer_size)
if not data: break
print("received data:", data)
conn.send(data) # echo
conn.close()
Just use a different port. Both the client and server should have the same port and host if not it won't work. Make sure to run the server before the client script.
For client.py
import socket
host = '127.0.0.1'
port = 9879
buffer_size = 1024
text = "Hello, World!"
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((host, port))
text = text.encode('utf-8')
s.send(text)
data = s.recv(buffer_size)
s.close()
print("received data:", data)
For server.py
import socket
mysocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
buffer_size = 1024
text = "Hello, World!"
mysocket.bind(('127.0.0.1', 9879))
mysocket.listen(5)
(client, (ip,port)) = mysocket.accept()
print(client, port)
client.send(b"knock knock knock, I'm the server")
data = client.recv(buffer_size)
print(data.decode())
mysocket.close()
Just change the port number and it will work and if you are in python3 then you will have to encode and decode as socket recieves and sends only binary strings.
I have succeed in my server!
My server python script is below:
import socket
host='0.0.0.0'
port=2345
s=socket.socket()
s.bind((host,port))
s.listen(2)
while True:
conn,addr=s.accept()
print("Connected by",addr)
data=conn.recv(1024)
print("received data:",data)
conn.send(data)
conn.close()
My Client python script is below:
import socket
s=socket.socket()
host="xx.xx.xx.xx" #This is your Server IP!
port=2345
s.connect((host,port))
s.send(b"hello")
rece=s.recv(1024)
print("Received",rece)
s.close()
There is two points needed to be careful in the script:
1.The host of the Server must is
'0.0.0.0'
So that the python script could user all interfaces in the server
2.I have find the question's error through the prompt:
TypeError: a bytes-like object is required, not 'str'
It means every string message in the 'send' method need to convert to 'bytes-like object',So the correct is
s.send(b"hello")
It is important that this is b'hello' not is 'hello'
I was following a tutorial that used threading to start the server. Once I removed the threading then I was able to connect to it.

Basic Python TCP Socket Server & Client

My first question here, please be gentle :) I'm trying to setup a basic Python (2.7) TCP socket server that is multithreaded (I haven't got to the multithreaded part yet), and a client.
Here is the server:
# Basic TCP socket server
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
host = ''
port = 8888
s.bind((host, port))
s.listen(5)
while True:
c, addr = s.accept()
print("Connected to %s" % addr)
c.send("Hello socket")
c.close()
And here is the client:
# Basic TCP socket client
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
host = '127.0.0.1'
port = 8888
s.connect((host, port))
print s.recv(1024)
s.close()
When I run the server it seems to execute without errors, but when I run the client to connect, I don't see the message that should be printed out to my terminal window where server is running. Here is the error (as #Rawing pointed out):
Traceback (most recent call last): File "server.py", line 19, in
print("Connected to %s" % addr) TypeError: not all arguments converted during string formatting
As far as making the server multithreaded, I need to read up on that but any suggestions are welcome.
Thank You.
You have two problems in your code
Your use of the string-formatting operator % is incorrect in your server program. If you pass a tuple to % (and addr is a tuple), then each item in the tuple must match one formatting directive. This is why your server program is failing.
print("Connected to %s" % str(addr))
In both programs, you mention, but do not invoke, socket.close. Try these in the appropriate locations:
s.close()
c.close()
A simple implementation of a TCP server in python 3 (If you are willing to use it instead of 2.7)
Server:
import socketserver
class MyTCPHandler(socketserver.BaseRequestHandler):
def handle(self):
data = self.rfile.readline() # Receive data from client
self.wfile.write(new_data) # Send data to client
if __name__ == "__main__":
with socketserver.UDPServer((HOST, PORT), MyUDPHandler) as server:
server.serve_forever()
Client:
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock:
sock.connect((HOST, PORT)) # Connect
sock.sendall(bytes(data + "\n", "utf-8")) # Send data
received = str(sock.recv(1024), "utf-8") # Receive data synchronically
bind the server to an ip, eg: host='127.0.0.1, and it should work.
Update: I'm totally wrong. I fixed a few things in your scripts and assumed that was the issue, but it's not - as the reply below states, binding to ('', ) is perfectly valid.
Looks like your socket code is perfectly good, but falls over the print statement. I fixed it with print("Connected to {}".format(addr))

Error - global name 'SOL_SOCKET is not defined

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

Categories