Sending string via socket (python)

Question:

I have two scripts, Server.py and Client.py.
I have two objectives in mind:

  1. To be able to send data again and again to server from client.
  2. To be able to send data from Server to client.

here is my Server.py :

import socket

serversocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
host = "192.168.1.3"
port = 8000
print (host)
print (port)
serversocket.bind((host, port))

serversocket.listen(5)
print ('server started and listening')
while 1:
    (clientsocket, address) = serversocket.accept()
    print ("connection found!")
    data = clientsocket.recv(1024).decode()
    print (data)
    r='REceieve'
    clientsocket.send(r.encode())

and here is my client :

#! /usr/bin/python3

import socket

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
host ="192.168.1.3"
port =8000
s.connect((host,port))

def ts(str):
   s.send('e'.encode()) 
   data = ''
   data = s.recv(1024).decode()
   print (data)

while 2:
   r = input('enter')
   ts(s)

s.close ()

The function works for the first time (‘e’ goes to the server and I get return message back), but how do I make it happen over and over again (something like a chat application) ?
The problem starts after the first time. The messages don’t go after the first time.
what am I doing wrong?
I am new with python, so please be a little elaborate, and if you can, please give the source code of the whole thing.

Asked By: harveyslash

||

Answers:

import socket
from threading import *

serversocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
host = "192.168.1.3"
port = 8000
print (host)
print (port)
serversocket.bind((host, port))

class client(Thread):
    def __init__(self, socket, address):
        Thread.__init__(self)
        self.sock = socket
        self.addr = address
        self.start()

    def run(self):
        while 1:
            print('Client sent:', self.sock.recv(1024).decode())
            self.sock.send(b'Oi you sent something to me')

serversocket.listen(5)
print ('server started and listening')
while 1:
    clientsocket, address = serversocket.accept()
    client(clientsocket, address)

This is a very VERY simple design for how you could solve it.
First of all, you need to either accept the client (server side) before going into your while 1 loop because in every loop you accept a new client, or you do as i describe, you toss the client into a separate thread which you handle on his own from now on.

Answered By: Torxed

This piece of code is incorrect.

while 1:
    (clientsocket, address) = serversocket.accept()
    print ("connection found!")
    data = clientsocket.recv(1024).decode()
    print (data)
    r='REceieve'
    clientsocket.send(r.encode())

The call on accept() on the serversocket blocks until there’s a client connection. When you first connect to the server from the client, it accepts the connection and receives data. However, when it enters the loop again, it is waiting for another connection and thus blocks as there are no other clients that are trying to connect.

That’s the reason the recv works correct only the first time. What you should do is find out how you can handle the communication with a client that has been accepted – maybe by creating a new Thread to handle communication with that client and continue accepting new clients in the loop, handling them in the same way.

Tip: If you want to work on creating your own chat application, you should look at a networking engine like Twisted. It will help you understand the whole concept better too.

Answered By: gravetii

client.py

import socket

s = socket.socket()
s.connect(('127.0.0.1',12345))
while True:
    str = raw_input("S: ")
    s.send(str.encode());
    if(str == "Bye" or str == "bye"):
        break
    print "N:",s.recv(1024).decode()
s.close()

server.py

import socket

s = socket.socket()
port = 12345
s.bind(('', port))
s.listen(5)
c, addr = s.accept()
print "Socket Up and running with a connection from",addr
while True:
    rcvdData = c.recv(1024).decode()
    print "S:",rcvdData
    sendData = raw_input("N: ")
    c.send(sendData.encode())
    if(sendData == "Bye" or sendData == "bye"):
        break
c.close()

This should be the code for a small prototype for the chatting app you wanted.
Run both of them in separate terminals but then just check for the ports.

Answered By: Nischaya Sharma

I modified @Torxed‘s answer a little bit and added the usage of a symmetric encryption algorithm (AES) with a secret key that is known only to the client and server. Now it’s a little bit more secure 🙂

Just make sure to create a new secret key using Fernet.generate_key()

Also you might need to install cryptography e.g.: pip install cryptography

Server code:

import socket, ssl
from threading import Thread
from cryptography.fernet import Fernet

serversocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
host = "111.111.111.11" # local ipv4 address, as seen in cmd > ipconfig > ipv4
port = 24836
secret_key = b'58RiNFG-2LEjRqkfVcCv-d5euem2LOxFBp0VaD_ft_M='

serversocket.bind((host, port))

class client(Thread):
    def __init__(self, socket, address):
        Thread.__init__(self)
        self.sock = socket
        self.addr = address
        self.start()

    def run(self):
        f = Fernet(secret_key)
        while True:
            try:
                message = self.sock.recv(1024)
                if not message:
                    break
                decrypted_message = f.decrypt(message)
                print('Client:', decrypted_message.decode())
                encrypted_response = f.encrypt(b'Message Received.')
                self.sock.send(encrypted_response)
            except ConnectionResetError:
                print(f'Client disconnected')
                break
        self.sock.close()

serversocket.listen(5)
print(f'Server started and listening on {host}:{port}')
while True:
    clientsocket, address = serversocket.accept()
    print(f'New client connected: {address[0]}:{address[1]}')
    client(clientsocket, address)

Client code:

import socket, ssl
from cryptography.fernet import Fernet

clientsocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
host = "111.111.111.11" # servers ip4 address
port = 24836
secret_key = b'58RiNFG-2LEjRqkfVcCv-d5euem2LOxFBp0VaD_ft_M='

clientsocket.connect((host, port))

while True:
    message = input('Client: ')
    f = Fernet(secret_key)
    encrypted_message = f.encrypt(message.encode())
    clientsocket.send(encrypted_message)
    response = clientsocket.recv(1024)
    decrypted_response = f.decrypt(response)
    print('Server:', decrypted_response.decode())
    
clientsocket.close()
Answered By: Mika C.
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.