Implement both HTTP and HTTPS on my simple Python socket server - python

I want my visitors to be able to use both HTTP and HTTPS. I am using a simple Python webserver created with socket. I followed this guide: Python Simple SSL Socket Server, but it wasn't that helpful because the server would crash if the certificate cannot be trusted in one of the clients. Here is a few lines of code from my webserver that runs the server:
def start(self):
# create a socket object
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# bind the socket object to the address and port
s.bind((self.host, self.port))
# start listening for connections
s.listen(100)
print("Listening at", s.getsockname())
while True:
# accept any new connection
conn, addr = s.accept()
# read the data sent by the client (1024 bytes)
data = conn.recv(1024).decode()
pieces = data.split("\n")
reqsplit = pieces[0].split(" ");
# send back the data to client
resp = self.handleRequests(pieces[0], pieces);
conn.sendall(resp)
# close the connection
conn.close()

Have another service (something like nginx) handle the https aspect, then configure the service to reverse proxy to your python server

Related

A request to send or receive data was disallowed because the socket is not connected in Python

I'm trying to make a console chat app in python using socket library.
Whenever I send a message to the server, the server code crashes with the following message:
OSError: [WinError 10057] A request to send or receive data was disallowed because the socket is not connected and (when sending on a datagram socket using a sendto call) no address was supplied
Server code
import socket
HOST = socket.gethostbyname(socket.gethostname()) # get the ip address of PC
PORT = 5050
ADDRESS = (HOST, PORT)
socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
socket.bind(ADDRESS)
while True:
socket.listen()
conn, addr = socket.accept()
print(f"Connected by {addr}")
while True:
data = conn.recv(64)
print(data.decode('utf-8'))
socket.send(data)
Client code
import socket
HOST = socket.gethostbyname(socket.gethostname()) # get the ip address of PC
PORT = 5050
ADDRESS = (HOST, PORT)
socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
socket.connect(ADDRESS)
while True:
msg = input("Enter your message")
socket.send(msg.encode('utf-8'))
data = socket.recv(64)
print(data.decode('utf-8'))
What I am trying to achieve is whenever I send a message to the server, the client script should print the sent message. How can I fix that?
You're attempting to send data to your own server socket. You instead want to send to the client that you accepted.
socket.send(data)
Should be:
conn.send(data)
If you think about it, if you had multiple clients, how would you send data to a specific client? By using the socket that accept gave you.
As a side note, you probably don't want to import the module as socket, and also call your variable socket. It's fine here, but if you were to make a more complicated project, you may accidentally refer to the object when you meant to refer to the module. I'd rename the socket object to sock or server_socket to avoid shadowing.

Anyone know how to change from the tcp protocol to the http one

I would like to know if anyone was able to change this code so that instead of it running on a wifi network it ran on http. I did all i could but i do not think there are any tutorials on how to preform this changing.
Server:
import socket
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
host = ''
port = 1234
server.bind((host, port))
server.listen(5)
run = True
client, addr = server.accept()
print('Got connection from',addr)
while run:
try:
data = input('>>>')
client.send(data.encode('UTF-8'))
msg = client.recv(1024)
print(msg.decode('UTF-8'))
except ConnectionResetError:
print('Client lost server connection')
print('Trying to connect . . .')
client, addr = server.accept()
print('Got connection from',addr)
Client:
import socket
import os
server = socket.socket()
host = '127.0.0.1'
port = 1234
run = True
server.connect((host,port))
while run:
msg = server.recv(1024)
os.popen(msg.decode('UTF-8'))
server.send('Client online . . .'.encode('UTF-8'))
I think you are confused on what TCP and HTTP is. TCP is part of layer 4 of the OSI model. HTTP is layer 7 of the OSI model.
Http is a protocol/standard used to exchange data with another Http enabled endpoint. Http is built on top of TCP. Http uses TCP to send data. The server has a TCP socket listening for data and once it receives data it then passes it along to another "process/program/line of code" to then parse that data using Http standards.
If you are wanting to use http to send/receive data you will need a web framework like Flask, Django or Starlette. They are Http servers with added features to allow you to code what you want to do with the data rather than handling the lower level stuff of parsing the http data being sent over TCP.
Http is a HUGE protocol/standard. If you try to do the parsing from scratch it is a big project to undertake.

How to send and receive message from client to client with Python (socket)?

We are working on a project "ByZantine Generals Problem" with Python(socket), we manage to create a successful connection between the server and the two clients (client1, client2). But we didn't know how to create a connection between the two clients , any help ?
Link model project problem : https://upload.wikimedia.org/wikipedia/commons/thumb/8/81/4generalestenientetraidor.svg/400px-4generalestenientetraidor.svg.png
Server.py
import socket
host = '192.168.43.209' # Standard loopback interface address
(localhost)
port = 65432 # Port to listen on (non-privileged ports are > 1023)
serv = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
serv.bind((host, port))
serv.listen(5)
while True:
conn, addr = serv.accept()
conn.send(b"Attack ")
data = conn.recv(4096)
if not data: break
print (data)
client1.py
import socket
host = '192.168.43.209' # Standard loopback interface address
(localhost)
port = 65432 # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))
from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 1 : ")
client2.py
import socket
host = '192.168.43.209' # Standard loopback interface address
(localhost)
port = 65432 # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))
from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 2 : ")
There are two approaches to make client 1 and client 2 communicate together.
Make them communicate through the server
This means they will communicate by just connecting to the server. And the server will forward the message between them.
To make this work, you need to make a function and pass their socket object to the function when they connect. In the function, you will just receive data from the client. Every time there is data received, you will broadcast it to all other clients.
Tip: You can add each client's socket object to a list so that you can easily broadcast the message to each client in the network.
Peer to peer communication
To communicate in p2p, they don't need to connect to the server. They will just communicate with each other directly. The preferred protocol for p2p communication is, UDP protocol.
If clients are gone exchange secure data like the server shouldn't access it, p2p is the best approach. Because there is no interference of the server while they are communicating.
You can do client to client communication through the server with something like this. Note: This is not currently tested because I am not on a computer where I can run this:
The core of this code is from this answer which explains how to send a message to ALL clients: https://stackoverflow.com/a/27139338/8150685
I used a list for clients but you may find it easier to use a dictionary.
clients = [] # The clients we have connected to
clients_lock = threading.Lock()
def listener(client, address):
print "Accepted connection from: ", address
with clients_lock:
clients.append(client) # Add a client to our list
try:
while True:
data = client.recv(1024)
if not data:
break
else:
print repr(data)
# Here you need to read your data
# and figure out who you want to send it to
client_to_send_to = 1 # Send this data to client 1
with clients_lock:
if client_to_send_to < len(clients):
clients[client_to_send_to].sendall(data)
finally:
with clients_lock:
clients.remove(client)
client.close()

Python Socket, how do i choose between s.send and conn.send?

def send_Button():
try:
myMsg = "ME: " + text.get()
msg = text.get()
conn.send(msg) ###
textBox.insert(END, myMsg + "\n")
textEntry.delete(0, END)
textBox.yview_pickplace("end")
except NameError:
myMsg = "ME: " + text.get()
msg = text.get()
conn.send(msg) ###
textBox.insert(END, myMsg + "\n")
textEntry.delete(0, END)
textBox.yview_pickplace("end")
This program uses the tkinter module with socket in python2.7. My program allows for you to either connect to a server to chat with or host a server for others to connect to you, but whenever I try and test it out then the lines with the '###' on always bring up an error and it doesn't work, the error which comes up is: "NameError: global name 'conn' is not defined" OR "error: [Errno 10057] A request to send or receive data was disallowed because the socket is not connected and (when sending on a datagram socket using a sendto call) no address was supplied".
Any help please?
I think that you are trying to get the program to act as a Client or as a Server just changing s.send() to conn.send() saddly it isn't that simple.
Socket Initializzation
The socket have to be initialized before sending or receiving data.
For a client usually it's something like this.
send_socket = socket.socket(socket.AF_INET,socket.SOCK_STREAM) # Create the socket
send_socket.connect((serverIp, serverPort)) # Connect to the server
send_socket.send(data) # Send the data to the server
And like this for a Server:
listen_socket = socket.socket(socket.AF_INET,socket.SOCK_STREAM) # Create the socket
listen_socket.bind(("0.0.0.0", port)) # Set the socket to accept client from every interface on the port port
listen_socket.listen(1) # Put the server on listen on the port setted before
accept_socket, addr = self.listen_socket.accept() # when a client connect return the socket to talk with it
data = self.accept_socket.recv(buffer_size) # Receive data form the client of max size buffer_size
Docs examples
From your question I guess that with s.send() and conn.send() you are talking about
this example from the python 2.7 socket docs
Here are four minimal example programs using the TCP/IP protocol: a server that echoes all data that it receives back (servicing only one client), and a client using it. Note that a server must perform the sequence socket(), bind(), listen(), accept() (possibly repeating the accept() to service more than one client), while a client only needs the sequence socket(), connect(). Also note that the server does not sendall()/recv() on the socket it is listening on but on the new socket returned by accept().
Client
Echo client program
import socket
HOST = 'daring.cwi.nl' # The remote host
PORT = 50007 # The same port as used by the server
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((HOST, PORT))
s.sendall('Hello, world')
data = s.recv(1024)
s.close()
print 'Received', repr(data)
the client is pretty stright forward, it create the socket s and then after using s.connect() it just send data through it.
Server
The server one is where there there are both s and conn
Echo server program
import socket
HOST = '' # Symbolic name meaning all available interfaces
PORT = 50007 # Arbitrary non-privileged port
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((HOST, PORT))
s.listen(1)
conn, addr = s.accept()
print 'Connected by', addr
while 1:
data = conn.recv(1024)
if not data:
break
conn.sendall(data)
conn.close()
in this one first of all we create a socket s on which the server will listen and then using s.accept() it will wait till a client connect to the server and then return the conn which is the socket of the connected client.
So to receive or send data to the client you have to use conn.
Notes
As said in the documentation in these two example the server accept only one client. So if you want to deal with multiple clients you have to repeat the accept step and possibly generate a new Thread for each client so that other clients don't have to wait for each others.

Server send data in python

I'm writing a simple client server app in python, where the client is listening every type of data entering in the specific port, and I want to when receiving a data flow, send back to the connected client (which have a dinamic ip) a string, in this case "001". But when I try to send the message, it fails!
#!/usr/bin/env python
import socket
TCP_IP = '192.168.1.115'
TCP_PORT = 55001
BUFFER_SIZE = 1024
MESSAGE = '01'
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((TCP_IP, TCP_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
print ('Sending data to client...')
addr change every connection .. i cannot manage this!
s.connect((addr, TCP_PORT))
s.send(MESSAGE)
data = s.recv(BUFFER_SIZE)
s.close()
(Connected stream) sockets are bidirectional, so there's no need to call connect to get a connection to the client—you already have one.
But you want to know why your code fails. And there are at least three problems with it.
First, after you call listen or connect on a socket, you can't call connect again; you will get an exception (EISCONN on POSIX, something equivalent on Windows). You will have to create a new socket.
Second, is client actually binded and listening for a connection on the same port as the server? If not, your connect can't work. If so, the bind will fail if the client and server are on the same machine.
Third, the addr you get back from accept is a (host, port) pair, not just a host. So, as written, you're trying to connect((('192.168.1.115', 12345), 55001)), which obviously isn't going to work.
You are trying to reply to the client using the server listening socket (s). This is only possible in UDP Servers. Since this is a TCP Server you have to use the conn which is crated using s.accept() to communication with remote client.

Categories