For some reason i cant seem to be able to create a host or client where the client can always send a message to the host whenever . i can only send one message and after that nothing is received .
my while loops should allow me to do this so i don't know why this is no achievable for me ;'()
#Host server
import socket
server_host= 'localhost'
server_port= 88
server = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
server.bind((server_host,server_port))
server.listen(5)
print('listening on {} port {}'.format(server_host,server_port))
while True:
client,addr = server.accept()
recieve = client.recv(2024)
print(recieve.decode())
Client :
# Python-Socket-Client
import socket
#'localhost'
# 88
target_server = str(input('Target_Host:'))
target_port = int(input('Target_Port:'))
client = socket.socket(socket.AF_INET , socket.SOCK_STREAM )
client.connect((target_server,target_port))
print('\n')
print('****************************')
print(target_server)
print(target_port)
def send_and_recieve_message(message):
#response = client.recv(4065)
if type(message) == str:
client.send(message.encode())
while True:
mess= input("{}:".format('Client'))
send_and_recieve_message(mess)
In your host code server.accept() is a blocking call. It will wait until someone connects. You need to separate it out of your while loop. And then check if the connection is still valid if not wait for another connection.
while True:
client,addr = server.accept()
while client != None:
recieve = client.recv(2024)
print(recieve.decode())
Something similar to this you probably will want to add a better check to see if the connection is still valid.
Related
I have been trying to create a messaging service in python using sockets. I have written the code to host two connections and allow one to send messages to the other using username and host_addr.
But every time I try to connect the second client and send a message from the first getting the following error.
ConnectionResetError: [Errno 54] Connection reset by peer
Server.py
import socket
import _thread as thread
HOST = "127.0.0.1" # Standard loopback interface address (localhost)
PORT = 1237 # Port to listen on (non-privileged ports are > 1023)
user_mapping = {}
def on_new_client(conn, addr):
data = conn.recv(1024)
data = data.decode()
print(data)
print(user_mapping)
if data[:8] == "username":
user_mapping[data[9:]] = (addr, data[9:])
elif data[0] == "#":
for i in user_mapping.values():
if i[0] == addr:
from_user = i[1]
else:
str = "user not found"
conn.sendto(str.encode(), addr)
str = "%s:%s" % (from_user, data[data.find(":") + 1:])
conn.sendto(str.encode(), user_mapping[data[1:data.find(":")](0)])
else:
pass
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((HOST, PORT))
s.listen(10)
while True:
conn, addr = s.accept()
thread.start_new_thread(on_new_client,(conn,addr))
s.close()
Client.py
import socket
HOST = "127.0.0.1" # The server's hostname or IP address
PORT = 1237 # The port used by the server
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((HOST, PORT))
username = input("Enter user name")
str = "username: %s" % username
s.send(str.encode())
while True:
message = input(username+">")
s.send(message.encode())
data = s.recv(1024)
print(data)
Was hoping some would could answer why this is happening and guide me to any good links where there is Information on creating a messaging service in python.
Client is sending 2 messages and then receiving one.
But server just listen once and then send one or two packages.
Chronologically:
Client sends a package, and server reads it.
Then both client and server try to send a package. Both packages that won't meet a listening peer.
Then client try to receive a package, but server won't send (he already sent it before) or it may send but its too late because communication is already broken.
Concepts you may implement always:
If one talk, another one may listen.
If a package is mean to be sent, it shall be sent anyway. Dont let a 'if' statment that send package when at 'else' that does not (or viceversa).
==== EDIT ====
About solution:
You need to work with paralel loops.
Take a look at this code https://www.neuralnine.com/tcp-chat-in-python/
He uses two threads on client, one for keep listening for new server updates (messages for other people) and another one to wait input from user.
I have a python reverse shell that I am working on that utilizes a client-server connection using TCP. I am testing them both right now on my localhost windows machine and I am utilizing the subprocess library to handle commands. The client is supposed to send a command to the server and the server will reply back with the output.
Server:
import socket
import subprocess
import os
# Server
# creates TCP socket
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# port and server ip(localhost)
LOCAL_HOST = '127.0.0.1'
PORT = 5565
BUFFER_SIZE = 5000 # size of message
no_char_message = "-1: Please enter a command"
# test connection
print("Server starting up on %s with port number %s" % (LOCAL_HOST, PORT))
# bind socket to ip and port
sock.bind((LOCAL_HOST, PORT))
# listen to socket
sock.listen(1)
# socket will accept connection and client address
print("Waiting for connection") # waiting for connection
connection, address = sock.accept() # accept connection with client address
print("Connected to", address) # connected by address
while True:
command = connection.recv(BUFFER_SIZE) # receive message from client
if not command:
break
if len(command) == 0:
connection.send(str.encode(no_char_message))
if len(command) > 0:
terminal = subprocess.Popen(command[:].decode("utf-8"), shell=True, stdout=subprocess.PIPE,
stderr=subprocess.PIPE, stdin=subprocess.PIPE)
output = terminal.stdout.read() + terminal.stderr.read()
output_as_string = str(output, "utf-8")
connection.send(str.encode(output_as_string))
print(output_as_string)
print("Closing Server")
sock.close()
connection.close()
Client
import socket
# Client
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # creates TCP Socket
# local host and port
LOCAL_HOST = '127.0.0.1'
PORT = 5565
BUFFER_SIZE = 5000 # size of message
# connect socket to ip and port
sock.connect((LOCAL_HOST, PORT))
print("Connected to server\n")
while True:
message = input("Please enter a command:\n") # ask user to input message
if message == 'quit':
break
print("Sending %s" % message)
sock.send(str.encode(message)) # send message
command = str(sock.recv(BUFFER_SIZE), "utf-8") # receive message
print("received %s" % command)
print("closing connection with server")
sock.close()
The issue is when I send an empty message to the server it hangs and just says sending in the terminal and the server never receives anything. I am not sure what is causing this but I am assuming the pipes are being blocked or that I am not handling this correctly.
I want the server to return an error message to the client rather than handle the message error in the client itself.
I tried checking the condition if the length of the command is 0 and handling it with an error message but it did not work and still hangs.
The program also seems to hang when I try for example the date command.
In general, how do I handle the condition if a command is not recognized, empty or doesn't execute successfully?
TCP has no concept of an empty message. TCP has no concept of a message at all, it knows only bytes. Thus, if you call send with an empty string it will simply send nothing (not an empty packet but no packet at all) to the server which means that there is nothing for the server to receive - it will still block while waiting for data. In other words: there is no empty command, there is simply no comment at all.
if len(command) == 0:
This will not check for an empty message (which again does not exist) but will trigger if the client closes the connection. Any check for an empty command had to be done at the client already.
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.
I am learning how to use python sockets right now, and now I am trying to use the simple chat program that I created to talk with one of my friends. of course, the porgram didnt work because I didnt port forward it.
I have forwarded port 21342 using the ip (the ip is static) I found at whatismyip.com as my external ip and the ip shown as the ipv4 in the oputput of the ipconfig command in the cmd as the internal ip.
now, even after forwarding it still isnt working. am I still missing something obvious or is this a real issue?
code:
server:
import socket
import threading as thread
sock = socket.socket(socket.AF_INET , socket.SOCK_STREAM)
host = ''
sock.bind((host , 21342))
sock.listen(5)
connections = []
def chat(client , address):
global connections
while True:
info = client.recv(1024)
for connection in connections:
if connection != client:
connection.send(info)
if not info:
connections.remove(client)
client.close()
break
try:
while True:
client , address = sock.accept()
print 'new connection!'
client_thread = thread.Thread(target = chat , args = (client , address))
client_thread.daemon = True
client_thread.start()
connections.append(client)
sock.close()
except:
for connection in connections:
connection.close()
sock.close()
client:
import socket
import threading as thread
sock = socket.socket(socket.AF_INET , socket.SOCK_STREAM)
host = 'ip found at whatsmyip.com'
sock.connect((host , 21342))
def get_info(sock):
while True:
print sock.recv(1024)
get_info_thread = thread.Thread(target = get_info , args = [sock])
get_info_thread.daemon = True
get_info_thread.start()
while True:
sock.send(raw_input())
sock.close()
I just can't manage to add Multithreading to my UDP Server.
A second client can connect, but instantly gets thrown out of the server when someone is already connected to it.
Could this be caused by something other than SingleThreading?
import sys, socket
localPort, remoteHost, remotePort = sys.argv[1].split(':')
try:
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.bind(('', localPort))
except:
fail('Failed to bind on port ' + str(localPort))
knownClient = None
knownServer = (remoteHost, remotePort)
sys.stderr.write('Ready.\n')
while True:
data, addr = s.recvfrom(32768)
print addr
if knownClient is None:
knownClient = addr
if addr == knownClient:
try:
s.sendto(data, knownServer)
except:
pass
else:
try:
s.sendto(data, knownClient)
except:
pass
You cannot write an UDP proxy with only port. How should you know from the answer of the server to which of the two connected clients you should send your answer. You have to open for each client a new socket to the remote server.
It's not Python but "networking" and for sure not "multithreading". You need to either direct the clients to different ports or create a new outgoing socket for each new client connection.
Because you have multiple sockets a very effective approach is to sit on select and wait for the incoming calls.
In order to identify the clients, it is also needed to keep a reference of the local addresses the new sockets are using to talk to the server.
Your code reworked to open a socket on each new incoming client connection. No guarantees, because that would involve network testing against an scenario (yours) which is unknown.
For a very robust implementation you would have to add error checking, socket removal for gone connections ...
import select
import socket
import sys
localPort, remoteHost, remotePort = sys.argv[1].split(':')
try:
server = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
server.bind(('', localPort))
except:
fail('Failed to bind on port ' + str(localPort))
localaddr = s.getsockname() # (localhost, localport)
remaddr = (remoteHost, remotePort)
sys.stderr.write('Ready.\n')
allsockets = [server]
proxysocks = dict()
origins = dict()
while True:
toread, _, _ = select.select(allsockets, [], [])
s = toread[0] # 1st socket available to read
data, orig = s.recvfrom(32768) # data, (remhost,remport)
dest = s.getsockname() # (localhost, localport)
if dst == localaddr: # client -> localserver
try:
p = proxysocks[orig] # find proxy sock
except KeyError: # new client connection
proxysocks[orig] = p = socket.socket(socket.AF_INET,
socket.SOCK_DGRAM)
proxyaddr = p.getsockname() # keep local address of new socket
origins[proxyaddr] = orig # link proxyaddr -> clientaddr
allsockets.append(p) # make it "selectable"
p.sendto(remaddr, data) # send to server
else: # server -> proxyaddr
s.sendto(origins[dstaddr])