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()
Related
I'm just very confused still about the basic socket process. Tried multiple ways to try and get the socket to connect but it keeps refusing.
client code- socket_client.py
import socket
host = socket.gethostname()
port = 8080
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host,port))
res = client.send (b' testing data send...')
client.close()
server code- server_client.py
import socket
host = socket.gethostname()
port = 8080
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind((host, port))
server.listen(10)
x=0
server_data = []
while True:
conn, addr = server.accept()
data = conn.recv(4096).decode()
x += 1
print ('Servicing client at %s'%addr[0])
server_data = client.recv(4096)
client_close()
server.close()
You have some problems in your server. You read from the connection but never use it, and you do client.recv when there is no variable client. This works:
import socket
host = socket.gethostname()
port = 8080
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind((host, port))
server.listen(10)
x=0
server_data = []
while True:
conn, addr = server.accept()
x += 1
print ('Servicing client at %s'%addr[0])
data = conn.recv(4096).decode()
print( "Received", data )
conn.close()
server.close()
Do remember that Python has a SocketServer module that can make some of this easier. If you need to get fancier, there are few modules better than Twisted at this kind of thing.
ALSO remember that the server must be running before you start the client. Someone has to be listening, otherwise the connection is rejected.
I have put together a server and client code to use in a messaging app. When I run the server and starts one client, everything works fine. When I start a second client, I can send messages from the first client and the second client will recieve them. I can send one message from the second client and the first client will recieve this first message. But after this message, the second client can not send or the server can not receive the data for some reason. The first client can still send messages.
I dont know where the mistake is, but I believe either the client can not .send() or the server can not .recv().
(I am quite new to programming so the code might be quite messy and not the most understandeble, and maybe there are several flaws...)
The server code
import socket
from _thread import *
import sys
HOST = "127.0.0.1"
PORT = 12000
client_socket = set()
def threaded(conn):
while True:
try:
data = conn.recv(1024).decode()
if not data:
print("Lost connection")
break
for conn in client_socket :
conn.send(data.encode())
except:
break
print("Gone")
conn.close()
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((HOST, PORT))
s.listen(5)
print("Server is up and running")
while True:
conn, addr = s.accept()
print("Connected to", addr)
client_socket .add(conn)
start_new_thread(threaded, (conn, ))
The client code
import threading
import socket, sys
HOST = "127.0.0.1"
PORT = 12000
check= ""
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((HOST, PORT))
def background():
while True:
answer= s.recv(1024).decode()
if check!= answer and answer!= "":
print(answer)
threading1 = threading.Thread(target=background)
threading1.daemon = True
threading1.start()
while True:
message= input()
if message!= "":
s.send(message.encode())
check = message
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])
I have a server written in python 2.7 that executes an infinite loop and process information from port 5000. Is it possible to change this connection port without restarting the server?
For example: the server is running in port 5000 and receives a 'change_port' option, the server module has to stop listening in port 5000 to start listening in port 7000. I don't know if i can manipulate sockets like that... Thanks
Once you have bound a socket to an address (interface, port) it cannot be changed. However, you can create a new socket (or many, depending on your needs) and bind it to your address (interface, port).
The code will differ based on the transport layer protocol you're using:
TCP:
# 1) Create first socket
s1 = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s1.bind(('0.0.0.0',5000))
# 2) Create second socket
s2 = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s2.bind(('0.0.0.0',7000))
# 3) Wait for a connection on the first socket
s1.listen(5)
sc, address = s1.accept()
# 4) Once a connection has been established...
# send, recv, process data
# until you need the next socket
# 5) Open connection on second socket
s2.listen(1)
sc2, address2 = s2.accept()
# now it probably a good time to tell the client (via s1) that s2 is ready
# client connects to s2
There you go
UDP (almost the same):
s1 = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s1.bind(('0.0.0.0',5000))
s2 = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s2.bind(('0.0.0.0',7000))
data, addr = s1.recvfrom(256)
s1.sendto("s2 ready",addr)
data2, addr2 = s2.recvfrom(256)
Simplified, but that's all there really is to it.
You might consider verifying that the address of the client from s1 is the same as the client connecting to s2.
No, it seems that you cannot run the socket.bind() method when its already bound. However, I have a solution you can use with the Asyncore module.
Heres my server:
import asyncore
import socket
class EchoHandler(asyncore.dispatcher_with_send):
def handle_read(self):
data = self.recv(8192)
if data:
print "Recieved Data: ", data, ". This server address:", self.getsockname()
class EchoServer(asyncore.dispatcher):
def __init__(self, host, port):
asyncore.dispatcher.__init__(self)
self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
self.set_reuse_addr()
self.bind((host, port))
self.listen(5)
def handle_accept(self):
pair = self.accept()
if pair is not None:
sock, addr = pair
print 'Incoming connection from %s' % repr(addr)
handler = EchoHandler(sock)
server = EchoServer('localhost', 56787)
server = EchoServer('localhost', 56788)
asyncore.loop()
Here are my clients:
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('localhost', 56787))
data = ""
while data.upper() != "Q":
data = raw_input("Enter something to send to the server")
s.send(data)
s.close()
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('localhost', 56788))
data = ""
while data.upper() != "Q":
data = raw_input("Enter something to send to the server")
s.send(data)
s.close()
This worked well, the python handled both ports. You should also be able to define seperate server classes for each of your ports.
I'm trying to create a basic server and client script. The idea is that the client can connect to the server and execute commands. Kinda like SSH but very simple. Heres my server code:
import sys, os, socket
host = ''
port = 50103
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((host, port))
print("Server started on port: ", port)
s.listen(1)
while (1):
conn, addr = s.accept()
print 'New connection from ', addr
try:
while True:
rc = conn.recv(2)
pipe = os.popen(rc)
rl = pipe.readlines()
fl = conn.makefile('w', 0)
fl.writelines(rl[:-1])
fl.close()
except IOError:
conn.close()
And here is my client:
import sys, socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
host = 'localhost'
port = input('Port: ')
s.connect((host, port))
while (1):
cmd = raw_input('$ ')
s.send(cmd)
file = s.makefile('r', 0)
sys.stdout.writelines(file.readlines())
file.close()
Here is my problem. I start the server and then run the client on the same machine. I enter the port and connect. Then I get the raw_input which is the '$'. If I type a command like 'ls' it just hangs on the client side. I have to exit the server for the client to receive the output of ls. By the way I am running Ubuntu Linux. Not sure if that matters.
When you makefile() on the socket and then use readlines() on it, it will continue until you reach an end of file, which in the socket case is that it closed from the other end.
Using makefile() in this case makes no sense to me, especially since you create it and close it after each command. Just use send() and recv() on both ends.
You probably also want to have some sort of actual "protocol" so the server tells the client "HERE COMES A RESPONSE" and "THIS IS THE END OF THE RESPONSE" so that the client knows. Otherwise it gets hard to know when to stop waiting for more response. :)
Update with an example that works:
server.py:
import sys, os, socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind(('', 50500))
print("Server started")
s.listen(1)
while True:
print "Accepting"
conn, addr = s.accept()
print 'New connection from ', addr
while True:
try:
rc = conn.recv(1024)
print "Command", rc
if not rc.strip():
continue
if rc.strip() == 'END':
print "Close"
conn.send("**END**")
conn.close()
break
else:
conn.send("This is the result of command %s\n" % rc)
except Exception:
conn.close()
sys.exit()
client.py
import sys, os, socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('localhost', 50500))
while True:
cmd = raw_input('$ ')
s.send(cmd)
result = s.recv(1024)
print result
if result == "**END**":
print "Ending"
break
Well for one thing you're only connecting on the client once and on the server you're closing the socket after every read.
You should take a look at this example.
http://ilab.cs.byu.edu/python/socket/echoserver.html
You're doing quite a few things incorrectly.