python3 socket server couldn't send FIN/ACK during sock.recv() - python-3.x

In this case, socket connection looks bit strange..
Server socket keeps to connect with client socket.
Client socket sends socket close ( FIN )
and then Server socket won't send automatically (FIN/ACK)
The reason is that FIN from client is converted to the message of length 0 by server socket.recv.
So, I revice it. (reference to the No1 in code)
But, in this code, server socket won't send FIN/ACK
although client.close and sock.close are executed.
Here is code
class PLC_Server(threading.Thread):
def __init__(self, ip_address="localhost", port=5000):
super(PLC_Server, self).__init__()
self.ip = ip_address
self.port = port
self.comm = {"address": self.ip + ":" + str(self.port)}
self.buffer_size = 4096
self.client = None
def _init_socket(self, listen_num=1):
# ソケットの生成。
self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.sock.bind((self.ip, int(self.port)))
self.sock.listen(listen_num)
def run(self):
self._init_socket()
while True:
self.client, address = self.sock.accept()
while True:
recv_data = self.client.recv(4096)
if recv_data == b"":
# No1
# FIN is convered to lenght 0 message by the sock.recv
print("Detect Client's socket close")
self.sock.close()
self.client.close()
self._init_socket()
break
else:
self.client.send("OK")
if __name__ == '__main__':
th1 = PLC_Server();
th1.start()

Related

Why isnt my python socket server receiving the messages?

so i am making a chatroom in python using sockets for practice. I have made the server code using threading so that i can have more clients. Ive also made the client code, and when i try to run two clients at once so that they message from one to another, they connect to server, but the server doesnt seem to be receiving the message sent from either of the clients.
SERVER CODE:
import select
from threading import *
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
# takes the first argument from command prompt as IP address
IP_address = "127.0.0.1"
# takes second argument from command prompt as port number
Port = int("50204")
server.bind((IP_address, Port))
server.listen(1000)
list_of_clients = []
def clientthread(conn, addr):
# sends a message to the client whose user object is conn
conn.send("Welcome to this chatroom!")
while True:
try:
message = conn.recv(4096)
if message:
print("<" + addr[0] + "> " + message.decode("UTF-8"))
# Calls broadcast function to send message to all
message_to_send = "<" + addr[0] + "> " + message
broadcast(message_to_send.encode("UTF-8"), conn)
else:
remove(conn)
except:
continue
def broadcast(message, connection):
for clients in list_of_clients:
if clients != connection:
try:
clients.send(message)
except:
clients.close()
# if the link is broken, we remove the client
remove(clients)
def remove(connection):
if connection in list_of_clients:
list_of_clients.remove(connection)
while True:
conn, addr = server.accept()
list_of_clients.append(conn)
# prints the address of the user that just connected
print(addr[0] + " connected")
# creates and individual thread for every user
# that connects
Thread(target=clientthread, args=(conn, addr))
conn.close()
server.close()
CLIENT CODE:
import socket
import sys
import time
class client:
def __init__(self):
self.server_ip = "127.0.0.1"
self.port = 50204
self.s = self.connect()
def connect(self):
try:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
except socket.error:
print("Failed to create socket.")
sys.exit()
print("Socket created")
try:
s.connect((self.server_ip, self.port))
except socket.error:
print("Failed to connect to ip " + self.server_ip)
print("Connected to: " + str(s.getsockname()))
return s
def SocketQuery(self, Sock, cmd):
try:
try:
# Send cmd string
Sock.send(cmd)
print("Sent!")
time.sleep(1)
except socket.error:
# Send failed
print("Send failed!")
sys.exit()
reply = Sock.recv(4096)
return reply
except ConnectionResetError:
print("Server is down!")
def SocketClose(self, Sock):
# close the socket
Sock.close()
time.sleep(.300)
if __name__ == "__main__":
c = client()
c.connect()
print("connected")
while True:
inp = input(">>> ")
if inp == ":q":
break
reply = c.SocketQuery(c.s, inp.encode("UTF-8"))
if reply:
print(reply.decode("UTF-8"))
c.SocketClose(c.s)
So as i have already mentioned, they do connect, but dont send/receive messages.
i have checked the value in conn.recv(), and it is the same, also everything gets encoded to UTF-8 before sent, and then decoded back. I cant seem to find any other problem except that im running them all on localhost.
If anyone knows the answer to this, please tell me.
cheers!

Why this Python3 chat fails after a few messages?

That's what happens: After the client sends some messages, it gives ConnectionAbortedError: [WinError 10053] and the server keeps running
Images:
server socket:
client socket:
Here's my server code:
from socket import *
def server(address, port):
sock = socket(AF_INET, SOCK_STREAM)
sock.bind((address, port))
sock.listen(10)
while True:
clientsock, addr = sock.accept()
ip, _ = addr
msg = input('YOU: ')
clientsock.send(bytes(msg, 'utf-8'))
data = clientsock.recv(2048)
print('%s - ' % ip, data.decode('utf-8'))
if not data:
break
clientsock.shutdown(SHUT_WR)
clientsock.close()
sock.close()
if __name__ == '__main__':
server('192.168.0.101', 5000)
Client:
from socket import *
def client(address, port):
sock = socket(AF_INET, SOCK_STREAM)
sock.connect((address, port)) #0.0.0.0 isnt valid
while True:
data = sock.recv(2048)
print('%s - ' % address, data.decode('utf-8'))
msg = input('YOU: ')
sock.send(bytes(msg, 'utf-8'))
sock.close()
if __name__ == '__main__':
client('192.168.0.101', 5000)
Server in each loop accept new client sends one message receive one message and disconnect client. Then it waits for another client.
You need another loop for handling client.
That another loop could be placed in another thread.
If you nest that loop in this loop, you will be able to handle just one client at the time. I modified your server like that:
def server(address, port):
sock = socket(AF_INET, SOCK_STREAM)
sock.bind((address, port))
sock.listen(10)
while True: # server loop
clientsock, addr = sock.accept()
ip, _ = addr
msg = "Hello to client from %s" % ip
# next line is here because your client need message from server to send message
clientsock.send(bytes(msg, 'utf-8'))
while True: # client loop
data = clientsock.recv(2048)
msg = '%s - %s' % (ip, data.decode('utf-8'))
print(msg)
if not data:
break
clientsock.send(bytes(msg, 'utf-8')) # for multiple clients you need send msg to all
clientsock.shutdown(SHUT_WR)
clientsock.close()
sock.close()
To handle multiple clients you do not want to block server loop until client loop ends. You could run client loop in another thread and continue waiting for next client clientsock, addr = sock.accept().
Similarly you might want to separate receiving messages from server and waiting for client input.

Python 3 socket client not connecting to server

I have a server.py and client.py pair. When I run the server on my machine and open multiple terminals to runs clients, I can connect fine. But when I try to run clients on another computer, the client never connects to the server. I'm pretty sure I tested this code a few months ago on multiple computers and it worked fine (though maybe I'm remembering wrong), but I think I updated my python version, so maybe that's why? How can I change my code below so it works?
server.py
import socket
from threading import Thread
import sys
clients = []
def recv(clientsocket):
while True:
msg = clientsocket.recv(1024) # wait for message from any of the clients.
print("\n" + msg.decode())
for c in clients: # send to all the clients.
c.send(msg)
def send(clientsocket):
while True:
msg = "[Server] %s" % input("\n") # wait for input
print(msg)
for c in clients: # send to all the clients.
c.send(msg.encode())
clientsocket.close()
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # Create a socket object
host = socket.gethostname() # Get local machine name
#port = 3001 # Reserve a port for your service.
port = int(input("Enter port: "))
print ('Server started at [%s]' % socket.gethostbyname(host))
print ('Waiting for clients...')
#s.bind((host, port)) # Bind to the port
s.bind((socket.gethostbyname(host), port))
s.listen(5) # Now wait for client connection.
while True:
#Waits until someone new to accept
c, addr = s.accept()
print(addr, "connected.")
clients.append(c)
thread_recv = Thread(target=recv, args=((c,)))
thread_recv.start()
thread_send = Thread(target=send, args=((c,)))
thread_send.start()
s.close()
client.py
import socket
from threading import Thread
hostname = input("Enter hostname/IP to connect to: ")
# port = 3001
port = int(input("Enter port: "))
clientsocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
clientsocket.connect((hostname, port))
def recv():
while True:
print("\n" + clientsocket.recv(2048).decode())
def send(username):
while True:
msg = "[%s] %s" % (username, input(""))
clientsocket.send(msg.encode()) # send message to the server.
username = input("Choose a username: ")
msg = "[%s has just connected]" % (username)
clientsocket.send(msg.encode())
thread_send = Thread(target=send, args=(username,))
thread_send.start()
thread_recv = Thread(target=recv, args=())
thread_recv.start()
while True:
# keep the threads going.
pass
Edit
Every time I start the server, it says my ip address is the same: 192.168.56.1. Even though I've turned my computer off and tried again. But when I go to Google and ask what is my ip address, it is something totally different. Why does the socket keep choosing 192.168.56.1? Is there something special about it? Is this something related to my problem?
Just bind you server to 0.0.0.0 and bind it to all network interfaces:
server.py
s.bind(('0.0.0.0', port))
Then the code in server.py will end up being something like this:
import socket
from threading import Thread
import sys
clients = []
def recv(clientsocket):
while True:
msg = clientsocket.recv(1024) # wait for message from any of the clients.
print("\n" + msg.decode())
for c in clients: # send to all the clients.
c.send(msg)
def send(clientsocket):
while True:
msg = "[Server] %s" % input("\n") # wait for input
print(msg)
for c in clients: # send to all the clients.
c.send(msg.encode())
clientsocket.close()
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # Create a socket object
host = socket.gethostname() # Get local machine name
#port = 3001 # Reserve a port for your service.
port = int(input("Enter port: "))
print ('Server started at [%s]' % socket.gethostbyname(host))
print ('Waiting for clients...')
#s.bind((host, port)) # Bind to the port
s.bind(('0.0.0.0', port))
s.listen(5) # Now wait for client connection.
while True:
#Waits until someone new to accept
c, addr = s.accept()
print(addr, "connected.")
clients.append(c)
thread_recv = Thread(target=recv, args=((c,)))
thread_recv.start()
thread_send = Thread(target=send, args=((c,)))
thread_send.start()
s.close()

Python UDP client-server with different matching incoming-outgoing ports

Based on the example at http://www.binarytides.com/programming-udp-sockets-in-python/ I modified it to run on python 3 and used two opposed ports on client and server, so replies from each one go to these ports. Here are my examples
Server:
'''
Simple udp socket server
'''
import socket
import sys
HOST = 'localhost'
PORT_IN = 8889 # Arbitrary non-privileged port
PORT_OUT = 8888
# Datagram (udp) socket
try :
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
print('Socket created')
except socket.error as e:
print(e)
sys.exit()
# Bind socket to local host and port
try:
s.bind((HOST, PORT_IN))
except socket.error as e:
print(e)
sys.exit()
print('Socket bind complete')
#now keep talking with the client
while 1:
# receive data from client (data, addr)
d = s.recvfrom(1024)
data = d[0]
addr = d[1]
if not data:
break
reply = 'OK...' + str(data)
s.sendto(reply.encode('UTF-8'), ('localhost', PORT_OUT))
print('Message[' + addr[0] + ':' + str(addr[1]) + '] - ' + str(data).strip())
s.close()
Client:
'''
udp socket client
Silver Moon
'''
import socket #for sockets
import sys #for exit
# create dgram udp socket
try:
s1 = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s2 = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
except socket.error:
print('Failed to create socket')
sys.exit()
host = 'localhost'
port_out = 8889
port_in = 8888
counter = 0
while(1) :
# msg = b'aoua'
msg = 'aoua' + str(counter)
try :
#Set the whole string
s1.sendto(msg.encode('UTF-8'), (host, port_out))
# receive data from client (data, addr)
s2.bind(('localhost', port_in))
d = s2.recvfrom(1472)
reply = d[0]
addr = d[1]
print('Server reply : ' + str(reply))
except socket.error as e:
print(e)
# sys.exit()
counter += 1
Problem is with the client which cannot receive any response from server and d = s2.recvfrom(1472) hangs with error [WinError 10022] An invalid argument was supplied.
I've noticed a slightly different behaviour with sock.settimeout(seconds), but I really can't figure why. Isn't d = s2.recvfrom(buffer) supposed to wait for incoming data?
What am I missing here?
Damn... Just saw it. Silly mistake. Calling s2.bind(('localhost', port_in)) in Client inside the loop.

Stop server from client's thread / Modify server's variable from client's thread

I would like to write an application that could stop the server based on client's input. The server is multi-threaded and I do not understand how can I do this.
Basically, I described my problem here: Modify server's variable from client's thread (threading, python).
However, this is the Python solution, not the general solution I could implement in Java, C, C++, etc.
I need to close other clients, when one of them guesses the number, but the server should be still alive, ready for the new game.
Can I ask for some advices, explanations?
I tried this (still do not know how to port it to C or Java), but it lets the clients send the numbers even if one of them just guesses it. It seems to me that kill_em_all does not do it's job, it does not close all the connections and does not disconnect the other clients as it should. How to improve this?
#!/usr/bin/env python
from random import randint
import socket, select
from time import gmtime, strftime
import threading
import sys
class Handler(threading.Thread):
def __init__(self, connection, randomnumber, server):
threading.Thread.__init__(self)
self.connection = connection
self.randomnumber = randomnumber
self.server = server
def run(self):
while True:
try:
data = self.connection.recv(1024)
if data:
print(data)
try:
num = int(data)
if self.server.guess(num) :
print 'someone guessed!'
self.server.kill_em_all()
break
else :
msg = "Try again!"
self.connection.sendall(msg.encode())
except ValueError as e:
msg = "%s" % e
self.connection.sendall(msg.encode())
else:
msg = "error"
self.connection.send(msg.encode())
except socket.error:
break
self.connection.close()
def send(self, msg):
self.connection.sendall(msg)
def close(self):
self.connection.close()
class Server:
randnum = randint(1,100)
def __init__(self, ip, port):
self.ip = ip
self.port = port
self.address = (self.ip, self.port)
self.server_socket = None
def guess(self, no):
if self.randnum == no:
self.randnum = randint(1, 100)
print("New number is ", self.randnum )
result = True
else:
result = False
return result
def kill_em_all(self):
for c in self.clients:
c.send("BYE!")
c.close()
def run(self):
try:
self.server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.server_socket.bind((self.ip, self.port))
self.server_socket.listen(10)
self.clients = []
print('Num is %s' % self.randnum)
while True:
connection, (ip, port) = self.server_socket.accept()
c = Handler(connection, self.randnum, self)
c.start()
self.clients.append(c)
except socket.error as e:
if self.server_socket:
self.server_socket.close()
sys.exit(1)
if __name__ == '__main__':
s = Server('127.0.0.1', 7777)
s.run()
Client code:
import socket
import sys
port = 7777
s = None
try:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
host = socket.gethostname()
s.connect(('127.0.0.1', port))
except socket.error, (value, message):
if s:
s.close()
print "Could not open socket: " + message
sys.exit(1)
while True:
data = raw_input('> ')
s.sendall(data)
data = s.recv(1024)
if data:
if data == "BYE!":
break
else:
print "Server sent: %s " % data
s.close()
Log in. Using whatever protocol you have, send the server a message telliing it to shut down. In the server, terminate your app when you get the shutdown message. That's it. It's not a problem with any OS I have used - any thread of a process can terminate that process.

Resources