I am trying to run a socket server on an aws ec2 ubuntu instance and then connecting with it using my local machine. I was successful with sending HTTP GET requests to my server hosted on aws ec2 instance and getting a response, but I am unable to connect the server and client using sockets, even after enabling custom TCP on the complete range of ports on the instance.
Here is a screenshot describing my instance's inbound and outbound rules :
screenshot
I used this python code from the internet to test socket networking :
socket_client.py :
import socket
def client_program():
host = "<aws instance public ip address>"
port = 8080 # socket server port number
client_socket = socket.socket() # instantiate
client_socket.connect((host, port)) # connect to the server
message = input(" -> ") # take input
while message.lower().strip() != 'bye':
client_socket.send(message.encode()) # send message
data = client_socket.recv(1024).decode() # receive response
print('Received from server: ' + data) # show in terminal
message = input(" -> ") # again take input
client_socket.close() # close the connection
if __name__ == '__main__':
client_program()
socket_server.py :
import socket
def server_program():
host = "0.0.0.0"
port = 8080 # initiate port no above 1024
server_socket = socket.socket() # get instance
# look closely. The bind() function takes tuple as argument
server_socket.bind((host, port)) # bind host address and port together
# configure how many client the server can listen simultaneously
server_socket.listen(2)
conn, address = server_socket.accept() # accept new connection
print("Connection from: " + str(address))
while True:
# receive data stream. it won't accept data packet greater than 1024 bytes
data = conn.recv(1024).decode()
if not data:
# if data is not received break
break
print("from connected user: " + str(data))
data = input(' -> ')
conn.send(data.encode()) # send data to the client
conn.close() # close the connection
if __name__ == '__main__':
server_program()
Note that the socket server-client are working completely fine when run on my local machine.
Please help if you know about how to fix this .
Edit - I have also tried with disabling firewall on the linux ec2 instance, but the problem still persists.
Thanks.
Related
What I wanted to do:
For learning about game programming I created an echo setup using a dedicated server and UDP. The dedicated server is in a different city (aka NOT in my local network).
On my local computer I have a udp client and server ( 2 different programs ). When I first started my python server I was immediately asked by windows firewall whether I want to add an exception. After allowing networking for my python server, I still did not receive any messages. (client -> dedicated server -/-> local server )
Only after I set a port forwarding in my router I was able to receive messages on my local UDP server.
My question is:
How do games solve that problem ? I don't activate a port forwarding for each multiplayer game I want to play and I'm still able to receive data in all these games.
My dedicated server setup (address and port intentionally changed):
#!/usr/bin/python3
import socket
ADDRESS = "1.123.123.123"
PORT = 12345
serverSock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
serverSock.bind((ADDRESS, PORT))
clientSock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
addresses = []
while True:
data, addr = serverSock.recvfrom(1024)
if addr not in addresses:
addresses.append(addr)
msg = str(data)
#if msg.split()
print("Message: " + str(data))
outMsg = str(addr) + ":" + msg
for ad in addresses:
print("Send Msg " + outMsg + " to " + ad[0] + ":" + str(PORT))
clientSock.sendto(bytes(outMsg, "utf-8"), (ad[0], 12345))
print("Addresses: " + str(addresses))
I figured this one out while writing up the question (like talking to the good old rubber duck):
The trick is not using 2 programs on the local computer. The program that sends the message also needs to retrieve the message. In my example it's blocking calls (ugly!), for a game you'd want to make that asynchronous. But this is the simplest way to get around the router firewall:
#! /usr/bin/python3
import socket
ADDRESS = "1.123.123.123"
PORT = 12345
clientSock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
# usually not required to bind a client, but we want to receive messages
clientSock.bind(("0.0.0.0",PORT))
while True:
msg = input("Enter message: ")
# Note that it is not required to send to the same port
# you have locally binded to.
clientSock.sendto(bytes(msg, "utf-8"), (ADDRESS, PORT))
# listen to the echo:
data, addr = clientSock.recvfrom(1024)
print(str(data) + " from " + str(addr))
However, my understanding on sockets and firewalls is limited. I do not understand why THIS works but 2 separated programs don't. Maybe someone could comment on that.
Hope I can save someone some time =)
I am trying to create a simple chat application with lua following are my files
-- load namespace
local socket = require("socket")
-- create a TCP socket and bind it to the local host, at any port
local server = assert(socket.bind("*", 0))
-- find out which port the OS chose for us
local ip, port = server:getsockname()
-- print a message informing what's up
print("Please telnet to localhost on port " .. port)
print("After connecting, you have 10s to enter a line to be echoed")
-- loop forever waiting for clients
local client = server:accept()
client:setoption("keepalive", true)
while 1 do
local line, err = client:receive()
print(line .. 'sent by client')
if not err then
client:send(line .. "\n")
else
print('error')
print(err)
end
end
client:close()
server.lua
local host, port = "127.0.0.1",arg[1]
local socket = require("socket")
local tcp = assert(socket.tcp())
tcp:connect(host, port);
--note the newline below
tcp:send("hello world\n");
while true do
local s, status, partial = tcp:receive()
print(s or partial)
print("enter message to send")
local message = io.read()
print("sending message" .. message)
tcp:send(message);
if status == "closed" then break end
end
tcp:close()
client.lua
Now I cannot get my head around that the server does not receive after the first hello world and how do i connect another client while the server is already connected to the client, does lua offer any callback for receive or connection established?
You never send any actual end of line to the server, after the first line. Since message will not contain any line end, client:receive() will wait for the end forever (because it reads a line from the socket).
You can try calling server:accept() multiple times to wait for a new client. Combined with a timeout and coroutines, you can serve multiple clients.
So I am trying to get a peer2peer matchmaking server going and I am having troubles with "sendto". I had some success with using "send" but then I couldn't do the hole punching step when the time came because it wouldn't switch peers to the other client for some reason. So now I am trying "sendto" but sendto cannot even send a message to the server.
Here is my code:
CLIENT:
local socket = require("socket")
local udp = socket.udp()
udp:setsockname("*", 0)
udp:settimeout(0)
--For server_ip I have also tried "localhost", "192.168.1.3", "127.0.0.1", and "127.0.0.0"
--none of them work. :(
local server_ip, server_port = "24.159.10.150", 30672
udp:sendto("FOO", server_ip, server_port)`
SERVER:
local socket = require("socket")
local udp = socket.udp()
udp:setsockname('*', 30672)
udp:settimeout(0)
while true do
local data, ip, port = udp:receivefrom()
if data ~= nil then
break;
end
end
print("SUCCESS!!")
So I am very new to networking and the Socket module in Python. So I watched some Youtube tutorials and found one on how to write the code for a simple server. My problem is right when the server receives data from the client, the server close() and loses connection to the client right when it receives the data. I want the server to automatically lose connection to the client but not "shutdown" or close(). I want to set it (if its possible) so that while the server is running in my Python Shell, if I want to close() the connection I use hot keys like for example "Control+E"? Here is my code so far:
#!/usr/bin/python
import socket
import sys
# Create a TCP/IP socket to listen on
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# Prevent from "adress already in use" upon server restart
server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
# Bind the socket to port 8081 on all interfaces
server_address = ('localhost',8081)
print ('starting up on %s port %s')%(server_address)
server.bind(server_address)
#Listen for connections
server.listen(5)
#Wait for one incoming connection
connection, client_address = server.accept()
print 'connection from', connection.getpeername()
# Let's recieve something
data = connection.recv(4096)
if data:
print "Recived ", repr(data)
#send the data back nicely formatted
data = data.rstrip()
connection.send("%s\n%s\n%s\n"%('-'*80, data.center(80),'-'*80))
# lose the connection from our side (the Server side)
connection.shutdown(socket.SHUT_RD | socket.SHUT_WR)
connection.close()
print 'Connection closed'
# And stop listening
server.close()
==================================================================================
Here is the code I am using (on the server side):
#!/usr/bin/python
import socket, sys
import select
srv = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
#Let's set the socket option reuse to 1, so that our server terminates quicker
srv.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
srv.bind(("localhost", 8081))
srv.listen(5)
while True:
print "Waiting for a client to connect"
(client, c_address) = srv.accept() #blocking wait for client
print "Client connected"
# Client has connected, add him to a list which we can poll for data
client_list = [client]
while close_socket_condition == 0:
ready_to_read, ready_to_write, in_error = select.select(client_list, [], [] , 1) #timeout 1 second
for s in ready_to_read: #Check if there is any socket that has data ready for us
data = client.recv(1024) # blocks until some data is read
if data:
client.send("echo:" + data)
client.close()
close_socket_condition = 1
And here is the error it is giving me when I try to send a string to the server:
data = s.recv(1024)
File "C:\Python27\lib\socket.py", line 170, in _dummy
raise error(EBADF, 'Bad file descriptor')
error: [Errno 9] Bad file descriptor
Here is example on a non-blocking socket read with similar structure as yours.
The server will establish a socket in localhost, and wait for a client to connect. After that it will start polling the socket for data, and also keep checking the exit condition close_socket_condition. Handling ctrl-e or other exit events will be left as an exercise :)
First we start socket, very much the same way as you:
#!/usr/bin/python
import socket, sys
import select
srv = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
#Let's set the socket option reuse to 1, so that our server terminates quicker
srv.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
srv.bind(("localhost", 8081))
srv.listen(5)
Then we declare our external exit condition close_socket_condition, and start eternal while loop that will always welcome new clients:
close_socket_condition = 0
while True:
print "Waiting for a client to connect"
(client, c_address) = srv.accept() #blocking wait for client
print "Client connected"
Now a client has connected, and we should start our service loop:
# Client has connected, add him to a list which we can poll for data
client_list = [client]
while close_socket_condition == 0:
Inside the service loop we will keep polling his socket for data and if nothing has arrived, we check for exit condition:
ready_to_read, ready_to_write, in_error = select.select(client_list, [], [] , 1) #timeout 1 second
for s in ready_to_read: #Check if there is any socket that has data ready for us
data = client.recv(1024) # blocks until some data is read
if data:
client.send("echo:" + data)
client.close()
close_socket_condition = 1
This code is simplified example, but the server will keep accepting new clients, and always reuse the connection. It does not handle client side terminations etc.
Hope it helps
I have a simple Python server which can handle multiple clients:
import select
import socket
import sys
host = ''
port = 50000
backlog = 5
size = 1024
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind((host,port))
server.listen(backlog)
input = [server,sys.stdin]
running = 1
while running:
inputready,outputready,exceptready = select.select(input,[],[])
for s in inputready:
if s == server:
# handle the server socket
client, address = server.accept()
input.append(client)
elif s == sys.stdin:
# handle standard input
junk = sys.stdin.readline()
running = 0
else:
# handle all other sockets
data = s.recv(size)
if data:
s.send(data)
else:
s.close()
input.remove(s)
server.close()
One client connects to it and they can communicate. I have a third box from where I am sending a RST signal to the server (using Scapy). The TCP state diagram does not say if an endpoint is supposed to try to recover a connection when it sees a RESET. Is there any way I can force the server to recover the connection? (I want it to send back a SYN so that it gets connected to the third client)
Your question doesn't make much sense. TCP just doesn't work like that.
Re "The TCP state diagram does not say if an endpoint is supposed to try to recover a connection when it sees a RESET": RFC 793 #3.4 explicitly says "If the receiver was in any other state [than LISTEN or SYN-RECEIVED], it aborts the connection and advises the user and goes to the CLOSED state.".
An RST won't disturb a connection unless it arrives over that connection. I guess you could plausibly forge one, but you would have to know the current TCP sequence number, and you can't get that from within either of the peers, let alone a third host.
If you succeeded somehow, the connection would then be dead, finished, kaput. Can't see the point of that either.
I can't attach any meaning to your requirement for the server to send a SYN to the third host, in response to an RST from the third host, that has been made to appear as though it came from the second host. TCP just doesn't work anything like this either.
If you want the server to connect to the third host it will just have to call connect() like everybody else. In which case it becomes a client, of course.