Here's the code, I wonder how to save the messages separately.
It can only get and send messages back to client. But I can't distinguish which are from client 1 and which are from client 2. Is there any way to save these messages into separate list or something else? so that I can distinguish them
Client 1:
import socket
import sys
messages = [b'This is client 1',
b'It is a good day!',
]
server_address = ('localhost', 1234)
socks = [ socket.socket(socket.AF_INET,
socket.SOCK_STREAM)
for i in range(1)]
print('connecting to %s port %s' % server_address)
for s in socks:
s.connect(server_address)
for message in messages:
for s in socks:
s.send(message)
for s in socks:
data = s.recv(1024)
print(data.decode())
if not data:
print(sys.stderr, 'closing socket', s.getsockname())
Client 2:
import socket
import sys
messages = [b'This is client 2',
b'It is raining today',
]
server_address = ('localhost', 5678)
socks = [ socket.socket(socket.AF_INET,
socket.SOCK_STREAM)
for i in range(1)]
print('connecting to %s port %s' % server_address)
for s in socks:
s.connect(server_address)
for message in messages:
for s in socks:
s.send(message)
for s in socks:
data = s.recv(1024)
print(data.decode())
if not data:
print(sys.stderr, 'closing socket', s.getsockname())
Server:
import selectors
import socket
sel = selectors.DefaultSelector()
def accept(sock, mask):
conn, addr = sock.accept()
print('accepted', conn, 'from', addr)
conn.setblocking(False)
sel.register(conn, selectors.EVENT_READ, read)
def read(conn, mask):
data = conn.recv(1000)
if data:
conn.send(data)
else:
print('closing', conn)
sel.unregister(conn)
conn.close()
sock = socket.socket()
sock.bind(('localhost', int(input())))
sock.listen(1)
sock.setblocking(False)
sel.register(sock, selectors.EVENT_READ, accept)
while True:
events = sel.select()
for key, mask in events:
callback = key.data
callback(key.fileobj, mask)
If you want to validate the ip on the network layer then you can use the variable addr that you create when you accept the connection.
However when you are doing this with multiple clients on the same host then it will not work since the ip is the same.
This will also not work if you are behind a NAT, because you would just get the IP of the nearest router in your network.
Another solution would be to validate the client on the application layer and simply give the client an identification value that you pass into the message that you send from the client.
Related
I have a server and I need it to receive multiple connections and messages.
The server receives new connections without problems but it doesn't get multiple messages from one connection.
import socket
import select
HEADER_LENGTH = 1024
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
try:
server_socket.bind((HOST, PORT))
except socket.error as e:
print(str(e))
print("Server is connected")
server_socket.listen(5)
sockets_list = [server_socket]
clients = {}
print("Server is listening")
def receive_message(conn):
try:
data = conn.recv(HEADER_LENGTH)
if not len(data):
return False
strdata = data.decode('utf-8')
print(strdata)
return strdata
except Exception as e:
print(e)
return False
def handle_client():
conn, addr = server_socket.accept()
print(f"Accepted new connection from {addr[0]}:{addr[1]}")
sockets_list.append(conn)
while True:
read_sockets, _, exception_sockets = select.select(sockets_list, [], [], 0)
for i in read_sockets:
if i == server_socket:
handle_client()
else:
print("received message")
message = receive_message(i)
if message is False:
sockets_list.remove(i)
try:
del clients[i]
except KeyError:
pass
continue
if message is not None:
clients[i] = message
if message is not None:
for client_socket in clients:
if client_socket != i:
client_socket.send(str.encode(message))
print("sent to all players")
What happens it that after receiving the first message, the server stops receiving messages from that connection.
And of course there is a lot more code but I showed you the relevant code.
I'll be very happy if someone helps me with that, I've surfed the web so much but haven't seen a solution for my problem.
updates:
I've tried to put socket.close() on my client side(written in Java) and then server gets maximum 2 messages and the problems with it are:
1. The server gets maximum 2 messages.
2. the connection changes(I need that the connection will stay static if possible)
try this code block
#-*- coding:utf-8 -*-
import socket
import sys
#get machine ip address
server_ip = socket.gethostbyname(socket.gethostname())
#create socket object
s = socket.socket()
#define port number
port = 6666
#bind ip and port to server
s.bind((server_ip,port))
#now waiting for clinet to connect
s.listen(5)
print("Enter this ip to connect your clinet")
print(server_ip)
clients = []
flag = True
recv_data = ""
if not clients:
c, addr = s.accept()
print("this is c ",c," this is Addr ",addr)
clients.append(c)
recv_data = c.recv(1024)
print(recv_data.decode("utf-8"))
if flag == True:
while recv_data.decode("utf-8") != "EX":
recv_data = c.recv(1024)
recv_data.decode("utf-8")
if recv_data.decode("utf-8") == "EX":
s.close()
print("check false")
break
s.close()
I have a listener on a tcp localhost:
HOST = '127.0.0.1' # The server's hostname or IP address
PORT = 8192 # The port used by the server
def client_socket():
while 1:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((TCP_IP,TCP_PORT))
s.listen(1)
while 1:
print 'Listening for client...'
conn, addr = s.accept()
print 'Connection address:', addr
data = conn.recv(BUFFER_SIZE)
if data == ";" :
conn.close()
print "Received all the data"
i=0
for x in param:
print x
#break
elif data:
print "received data: ", data
param.insert(i,data)
i+=1
#print "End of transmission"
s.close()
I am trying to send a JSON object to the same port on the local host:
HOST = '127.0.0.1' # The server's hostname or IP address
PORT = 8192 # The port used by the server
def json_message(direction):
local_ip = socket.gethostbyname(socket.gethostname())
data = {
'sender' : local_ip,
'instruction' : direction
}
json_data = json.dumps(data, sort_keys=False, indent=2)
print("data %s" % json_data)
send_message(json_data)
return json_data
def send_message(data):
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.connect((HOST, PORT))
s.sendall(data)
data = s.recv(1024)
print('Received', repr(data))
However, I get a socket error:
socket.error: [Errno 98] Address already in use
What am I doing wrong? Will this work or do I need to serialize the JSON object?
There are a few problems with your code, but the one that will likely address your issue is setting the SO_REUSEADDR socket option with:
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
after you create the socket (with socket.socket(...) but before you attempt to bind to an address (with s.bind().
In terms of other things, the two "halves" of the code are pretty inconsistent -- like you copied and pasted code from two different places and tried to use them?
(One uses a context manager and Python 3 print syntax while the other uses Python 2 print syntax...)
But I've written enough socket programs that I can decipher pretty much anything, so here's a working version of your code (with some pretty suboptimal parameters e.g. a buffer size of 1, but how else would you expect to catch a single ;?)
Server:
import socket
HOST = '127.0.0.1' # The server's hostname or IP address
PORT = 8192 # The port used by the server
BUFFER_SIZE = 1
def server_socket():
data = []
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.bind((HOST,PORT))
s.listen()
while 1: # Accept connections from multiple clients
print('Listening for client...')
conn, addr = s.accept()
print('Connection address:', addr)
while 1: # Accept multiple messages from each client
buffer = conn.recv(BUFFER_SIZE)
buffer = buffer.decode()
if buffer == ";":
conn.close()
print("Received all the data")
for x in data:
print(x)
break
elif buffer:
print("received data: ", buffer)
data.append(buffer)
else:
break
server_socket()
Client:
import socket
import json
HOST = '127.0.0.1' # The server's hostname or IP address
PORT = 8192 # The port used by the server
def json_message(direction):
local_ip = socket.gethostbyname(socket.gethostname())
data = {
'sender': local_ip,
'instruction': direction
}
json_data = json.dumps(data, sort_keys=False, indent=2)
print("data %s" % json_data)
send_message(json_data + ";")
return json_data
def send_message(data):
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.connect((HOST, PORT))
s.sendall(data.encode())
data = s.recv(1024)
print('Received', repr(data))
json_message("SOME_DIRECTION")
Here is my socket server and client:
import socket
import threading
import chardet
bind_ip = '0.0.0.0'
bind_port = 9999
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind((bind_ip, bind_port))
server.listen(1) # max backlog of connections
print (('Listening on {}:{}').format(bind_ip, bind_port))
def handle_client_connection(client_socket):
request = client_socket.recv(4096 )
result = chardet.detect(request)
print(result)
print (request.decode(result['encoding']))
client_socket.send('ACK!'.encode(result['encoding']))
client_socket.close()
while True:
client_sock, address = server.accept()
print (('Accepted connection from {}:{}').format(address[0], address[1]))
client_handler = threading.Thread(
target=handle_client_connection,
args=(client_sock,) # without comma you'd get a... TypeError: handle_client_connection() argument after * must be a sequence, not _socketobject
)
client_handler.start()
The client is this:
import socket
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect(('127.0.0.1', 9999))
client.send(str('test data').encode("utf-16"))
response = client.recv(4096)
print(response.decode("utf-16"))
How to make the socket server secured from DOS or DDos attacks?
I've made a TCP echo client/server with bits from here and here. How can I verify that the socket is encrypted and cannot be intercepted and read? I've tried using Wireshark, but both SSL and non-SSL show encrypted packets. This makes me question their validity.
Client:
import socket
import ssl
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_address = ('HOSTNAME', 10000)
print('Connecting to %s port %s' % server_address)
sock.connect(server_address)
ssl_sock = ssl.wrap_socket(
sock,
ssl_version = ssl.PROTOCOL_TLSv1_2
)
try:
message = str.encode(input('>>> '))
print('Sending "%s"' % message)
ssl_sock.sendall(message)
amount_received = 0
amount_expected = len(message)
while amount_received < amount_expected:
data = ssl_sock.recv(16)
amount_received += len(data)
print('Received "%s"' % data)
finally:
print('Closing socket')
ssl_sock.close()
Server:
import socket
import ssl
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_address = ('HOSTNAME', 10000)
print('Starting up on %s port %s' % server_address)
sock.bind(server_address)
sock.listen(1)
while True:
print('Waiting for a connection')
try:
connection, client_address = sock.accept()
stream = ssl.wrap_socket(
connection,
server_side = True,
certfile = 'fullchain.pem',
keyfile = 'privkey.pem',
ssl_version = ssl.PROTOCOL_TLSv1_2
)
except KeyboardInterrupt:
print('\nStopping server')
exit()
except:
print('ERROR')
continue
try:
print('Connection from', client_address)
while True:
data = stream.recv(16)
print('Received "%s"' % data)
if data:
print('Sending data back to the client')
stream.sendall(data)
else:
print('No more data from', client_address)
break
finally:
stream.close()
The server is running on my VPS and using the real certificate for HTTPS. Everything works, but I just want to be sure this test is secure before I build anything for real.
I have a python script that receives tcp data from client and I want to send a response to a specific client (I handle more than 500). This command comes from a mysql database and I handle the clientsocket by a dictionary, but the script is down when it receives a lot of connections.
How can I store the clientsocket in mysql database, or which is the best way to handle the clientsocket?
My code is:
import thread
from socket import *
def sendCommand():
try:
for clientsocket,id_client in conn_dict.iteritems():
if id_cliente == "TEST_from_mysql_db":
clientsocket.send("ACK SEND")
break
except:
print "NO"
def handler(clientsocket, clientaddr):
print "Accepted connection from: ", clientaddr
while 1:
data = clientsocket.recv(buf)
if not data:
break
else:
conn_dict[clientsocket] = id_client
sendCommand()
clientsocket.close()
if __name__ == "__main__":
conn_dict = dict()
host = str("XXX.XXX.XXX.XXX")
port = XXX
buf = 1024
addr = (host, port)
serversocket = socket(AF_INET, SOCK_STREAM)
serversocket.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)
serversocket.bind(addr)
serversocket.listen(2)
while 1:
print "Server is listening for connections\n"
clientsocket, clientaddr = serversocket.accept()
thread.start_new_thread(handler, (clientsocket, clientaddr))
serversocket.close()