I am writing a TCP server in Python.
I want the server to close the connection right after the server send the SYN-ACK (response to SYN from client) without waiting to the client's ACK response (without finishing the handshake).
That's my server:
def get_tcp(port, data_len=1024):
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.bind(('', port))
sock.listen(1)
conn, addr = sock.accept()
conn.close()
Is there a way to do it?
Thank you very much
Related
I'm developing an app and I want to send msgs from the client socket (TCP) to the server socket. I want to send 3 messages, send one, wait till the ACK from the server, send another msg wait till the ACK from the server...
This is my code (client side):
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock:
sock.connect((host,port))
sock.sendall(bytes(INIT_MSG, "UTF-8"))
sock.sendall(bytes(FREQ_MSG, "UTF-8"))
sock.sendall(bytes(KEY_MSG, "UTF-8"))
And in server side:
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.bind(("",PORT))
s.listen()
counter = 0
conn, addr = s.accept()
print("Connected by:", addr)
while True:
data = conn.recv(1024)
if not data:
break
But when I use Wireshark to look at the frames, all the data is send in one frame instead of 3. I believe the main problem is in the server side which accepts 1024b.
How can I fix it?
I copied the echo server example from the python documentation and it's working fine. But when I edit the code, so it wont send the data back to the client, the socket.recv() method doesn't return when it's called the second time.
import socket
HOST = ''
PORT = 50007
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 True:
data = conn.recv(1024)
if not data: break
conn.sendall(b'ok')
conn.close()
In the original version from the python documentation the while loop is slightly different:
while True:
data = conn.recv(1024)
if not data: break
conn.sendall(data)
Client's code:
import socket
HOST = 'localhost'
PORT = 50007
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((HOST, PORT))
s.sendall(b'Hello, world')
data = s.recv(1024)
s.close()
print('Received', repr(data))
TCP sockets are streams of data. There is no one-to-one correlation between send calls on one side and receive calls on the other. There is a higher level correlation based on the protocol you implement. In the original code, the rule was that the server would send exactly what it received until the client closed the incoming side of the connection. Then the server closed the socket.
With your change, the rules changed. Now the server keeps receiving and discarding data until the client closes the incoming side of the connection. Then the server sends "ok" and closes the socket.
A client using the first rule hangs because its expecting data before it closes the socket. If it wants to work with this new server rule, it has to close its outgoing side of the socket to tell the server its done, and then it can get the return data.
I've updated the client and server to shutdown parts of the connection and also have the client do multiple recv's in case the incoming data is fragmented. Less complete implementations seem to work for small payloads because you are unlikely to get fragmentation, but break horribly in real production code.
server
import socket
HOST = ''
PORT = 50007
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.bind((HOST, PORT))
s.listen(1)
conn, addr = s.accept()
print('Connected by', addr)
while True:
data = conn.recv(1024)
if not data: break
conn.sendall(b'ok')
conn.shutdown(socket.SHUT_WR)
conn.close()
client
import socket
HOST = 'localhost'
PORT = 50007
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((HOST, PORT))
s.sendall(b'Hello, world')
s.shutdown(socket.SHUT_WR)
data = b''
while True:
buf = s.recv(1024)
if not buf:
break
data += buf
s.close()
print('Received', repr(data))
The number of receive and send operations have to match because they are blocking. This is the flow diagram for your code:
Server listen
Client connect
Server receive (this waits until a message arrives at the server) [1]
Client send 'Hello world' (received by [1])
Server receive (because there was data received) [2]
Client receive [3]
Because the server and the client are blocked now, no program can continue any further.
The fix would be to remove the client's receive call because you removed the server's send call.
I'm trying to learn about sockets and how to create a server and a client in python.
While reading this great article from Real Python I had difficulties understanding why the server receives two strings, when I only send one.
server.py
import socket
HOST = "127.0.0.1"
PORT = 65432
server = socket.socket(
family=socket.AF_INET,
type=socket.SOCK_STREAM
)
with server:
server.bind((HOST, PORT))
server.listen()
print("Waiting for connections...")
conn, addr = server.accept()
print("Accepted!")
with conn:
print(f"Connected by {addr}")
while True:
data = conn.recv(1024)
print(f"Message received: {data}")
if not data:
print(f"Breaking while loop and closing connection")
break
conn.sendall(data)
client.py
import socket
HOST = "127.0.0.1"
PORT = 65432
client = socket.socket(
family=socket.AF_INET,
type=socket.SOCK_STREAM
)
with client as c:
c.connect((HOST, PORT))
# Get input from client
message = input("Enter your message: ")
c.sendall(str.encode(message))
data = c.recv(1024)
print(f"Received {data}")
Output from server.py after running the server and client:
Waiting for connections...
Accepted!
Connected by ('127.0.0.1', 64476)
Message received: b'message'
Message received: b''
Breaking while loop and close connection
Why does the server receive two messages (b'message' and b'')
The recv() can only empty string when the other end is gone. You are unable to send zero length data over socket (try it :). So the fact you are seeing this is simply because you are not checking for that.
PS: your client's last print() is not correctly indented.
I am attempting to connect a simple server and client from two computers on the same network. Both the client and server cannot 'find' each other, as they do not move past .connect() and .accept() respectively. What am I doing wrong?
(Windows 10)
Server:
import socket
HOST = socket.gethostname() #Returns: "WASS104983"
#I have also tried socket.gethostbyname(socket.gethostname)), returning: "25.38.252.147"
PORT = 50007
sock = socket.socket()
sock.bind((HOST, PORT))
sock.listen(5)
print("Awaiting connection... ")
(clnt, addr) = sock.accept()
print("Client connected")
…
and Client:
import socket
HOST = "WASS104983" #Or "25.38.252.147", depending on the servers setup
PORT = 50007
sock = socket.socket()
print("Attempting connection... ")
sock.connect((HOST, PORT))
print("Connected")
…
I have gotten this to work before so I am not sure why it's not now.
I know there are a few questions of this calibre, but none seem to cover my problem.
Also, a wifi extender should not interfere with local transmissions should it?
I have always seen servers setup as such:
import socket
import threading
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(5)
print("[*] Listening on {}:{}".format(bind_ip, bind_port))
def handle_client(client_socket):
request = client_socket.recv(1024)
print('received: {}'.format(request))
client_socket.send(b'ACK!')
client_socket.close()
while True:
client, addr = server.accept()
print("[*] Accepted connection from: {}:{}".format(addr[0], addr[1]))
client_handler = threading.Thread(target=handle_client, args=(client,))
client_handler.start()*
Where I think an important distinction from your post may be that the server accepting connections is within an infinite loop. Have you tried this?
There is Multi-client server situation in which a server is connected to multiple clients.
All the clients are messaging the server and the server is replying them well.
Now if one of the client floods the server with numerous packets then the server just stops receiving those packets from that client and still receives packets from other clients connected to it.
.Please help me doing this.
You only have to close the socket immediately after accepting it, if the connection comes form the banned client:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((HOST, PORT))
s.listen(1)
while True:
conn, addr = s.accept()
if addr[0] in banned_clients:
conn.close()
else:
proceed()