I'm trying to hack together a way to send messages between two computers. The following code creates a thread for receiving messages.
import socket # Import socket module
import threading
import traceback
def recv_one_message(sock):
lengthbuf = recvall(sock, 4)
length, = struct.unpack('!I', lengthbuf)
return recvall(sock, length)
def recvall(sock, count):
buf = b''
while count:
newbuf = sock.recv(count)
if not newbuf: return None
buf += newbuf
count -= len(newbuf)
return buf
host="ec2-35-160-33-3.us-west-2.compute.amazonaws.com"
kill_threads=False
def receive_thread():
while not kill_threads:
try:
# Create a socket object
soc = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
soc.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
port = 8502 # Reserve a port for your service.
soc.bind((host, port)) # Bind to the port
print("port bound")
soc.settimeout(10)
soc.listen(50000000) # Now wait for client connection.
conn, addr = soc.accept() # Establish connection with client.
soc.settimeout(None)
print ("Got connection from",addr)
while not kill_threads:
msg_binary=recv_one_message(soc)
msg=str(msg_binary, "utf-8")
print(msg)
except Exception:
traceback.print_exc()
try:
conn.close()
soc.close()
except Exception:
traceback.print_exc()
t2 = threading.Thread(target=receive_thread)
t2.daemon=True
t2.start()
I get the following error:
Traceback (most recent call last):
File "<ipython-input-3-eaef71a53845>", line 59, in receive_thread
msg_binary=recv_one_message(soc)
File "<ipython-input-3-eaef71a53845>", line 7, in recv_one_message
lengthbuf = recvall(sock, 4)
File "<ipython-input-3-eaef71a53845>", line 14, in recvall
newbuf = sock.recv(count)
OSError: [Errno 107] Transport endpoint is not connected
Here is my Scala sender that tries to connect to the Python part and sends "hello world" once a second.
import java.io._
import java.net._
import java.nio.charset.Charset
val host = "ec2-35-160-33-3.us-west-2.compute.amazonaws.com"
new Thread {
override def run() {
while (true) {
try {
print("trying to establish connection")
val soc = new Socket(host, 8502)
val dout = new DataOutputStream(soc.getOutputStream())
print("connection established")
val serializedMessage = "hello world"
val serializedMessageBytes = (serializedMessage).getBytes(Charset.forName("UTF-8"))
while (true) {
dout.write(serializedMessageBytes.length)
dout.write(serializedMessageBytes)
dout.flush()
Thread.sleep(1000)
}
} catch {
case e => e.printStackTrace()
}
}
}
}.start()
conn, addr = soc.accept() # Establish connection with client.
...
msg_binary=recv_one_message(soc)
You need to receive the data on the connected socket you got from accept (conn) and not on the listener socket (soc).
Related
I am attempting to piece together a secure socket client server communication solution. I do not have experience in doing so, so have cobbled together what I believe are relevant sections. The idea is that the Server waits for connections, the client creates a connection that is secure and then communication can take place.
The code also utilizes secure communication in authorization with client and server keys and certificates.
client code:
class Client:
def __init__(self):
try:
self.host, self.port = "127.0.0.1", 65416
self.client_cert = os.path.join(os.path.dirname(__file__), "client.crt")
self.client_key = os.path.join(os.path.dirname(__file__), "client.key")
self._context = ssl.SSLContext()
self._context.load_cert_chain(self.client_cert, self.client_key)
self._sock = None
self._ssock = None
except Exception as e:
print("Error in Initializing")
def checkvalidclient(self):
# ---- Client Communication Setup ----
HOST = self.host # The server's hostname or IP address
PORT = self.port # The port used by the server
try:
self._sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self._ssock = self._context.wrap_socket(self._sock,)
self._ssock.connect((HOST, PORT))
print ("Socket successfully created")
except socket.error as err:
print ("socket creation failed with error %s" %(err))
print('Waiting for connection')
Response = self._ssock.recv(1024)
while True:
Input = input('Say Something: ')
# s.send(str.encode(Input))
send_msg(self._ssock, str.encode(Input))
# Response = s.recv(1024)
Response = recv_msg(self._ssock)
if Response is not None:
print(Response.decode('utf-8'))
def closesockconnection(self):
self._ssock.close()
# ---- To Avoid Message Boundary Problem on top of TCP protocol ----
def send_msg(sock: socket, msg): # ---- Use this to send
# Prefix each message with a 4-byte length (network byte order)
msg = struct.pack('>I', len(msg)) + msg
sock.sendall(msg)
def recv_msg(sock: socket): # ---- Use this to receive
# Read message length and unpack it into an integer
raw_msglen = recvall(sock, 4)
if not raw_msglen:
return None
msglen = struct.unpack('>I', raw_msglen)[0]
# Read the message data
return recvall(sock, msglen)
def recvall(sock: socket, n: int):
# Helper function to receive n bytes or return None if EOF is hit
data = bytearray()
while len(data) < n:
packet = sock.recv(n - len(data))
if not packet:
return None
data.extend(packet)
return data
client = Client()
client.checkvalidclient()
Server code:
import socket
import os
import ssl
from os import path
from _thread import *
import struct # Here to convert Python data types into byte streams (in string) and back
# ---- To Avoid Message Boundary Problem on top of TCP protocol ----
def send_msg(sock: socket, msg): # ---- Use this to send
# Prefix each message with a 4-byte length (network byte order)
msg = struct.pack('>I', len(msg)) + msg
sock.sendall(msg)
def recv_msg(sock: socket): # ---- Use this to receive
# Read message length and unpack it into an integer
raw_msglen = recvall(sock, 4)
if not raw_msglen:
return None
msglen = struct.unpack('>I', raw_msglen)[0]
# Read the message data
return recvall(sock, msglen)
def recvall(sock: socket, n: int):
# Helper function to receive n bytes or return None if EOF is hit
try:
data = bytearray()
while len(data) < n:
packet = sock.recv(n - len(data))
if not packet:
return None
data.extend(packet)
return data
except Exception as e:
print("Exception in recvall : " + str(e))
# ---- Server Communication Setup
class Server:
def __init__(self):
self.HOST = '127.0.0.1' # Standard loopback interface address (localhost)
self.PORT = 65416 # Port to listen on (non-privileged ports are > 1023)
self.ThreadCount = 0
self.server_cert = path.join(path.dirname(__file__), "server.crt")
self.server_key = path.join(path.dirname(__file__), "server.key")
self.client_cert = path.join(path.dirname(__file__), "client.crt")
self._context = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH)
self._context.verify_mode = ssl.CERT_REQUIRED
self._context.load_cert_chain(self.server_cert, self.server_key)
self._context.load_verify_locations(self.client_cert)
self.sock = None
def connect(self):
try: # create socket
self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM, 0)
print ("Socket successfully created")
except socket.error as err:
print ("socket creation failed with error %s" %(err))
try: # bind socket to an address
self.sock.bind((self.HOST, self.PORT))
except socket.error as e:
print(str(e))
print('Waiting for a Connection..')
self.sock.listen(3)
def threaded_client(self, conn: socket):
conn.send(str.encode('Welcome to the Server'))
while True:
# data = conn.recv(2048) # receive message from client
data = recv_msg(conn)
print(data)
if data is not None:
reply = 'Server Says: ' + data.decode('utf-8')
if not data:
break
# conn.sendall(str.encode(reply))
send_msg(conn, str.encode(reply))
#conn.close()
def waitforconnection(self):
while True:
Client, addr = self.sock.accept()
self._context.wrap_socket(Client, server_side=True)
print('Connected to: ' + addr[0] + ':' + str(addr[1]))
start_new_thread(self.threaded_client, (Client, )) # Calling threaded_client() on a new thread
self.ThreadCount += 1
print('Thread Number: ' + str(self.ThreadCount))
#self.sock.close()
server = Server()
server.connect()
server.waitforconnection()
The lines:
def threaded_client(self, conn: socket):
conn.send(str.encode('Welcome to the Server'))
result in the error:
[WinError 10038] An operation was attempted on something that is not a socket
When I removed the certificate related lines in client:
self.client_cert = os.path.join(os.path.dirname(__file__), "client.crt")
self.client_key = os.path.join(os.path.dirname(__file__), "client.key")
self._context = ssl.SSLContext()
self._context.load_cert_chain(self.client_cert, self.client_key)
and the certificate related lines in the server:
self.server_cert = path.join(path.dirname(__file__), "server.crt")
self.server_key = path.join(path.dirname(__file__), "server.key")
self.client_cert = path.join(path.dirname(__file__), "client.crt")
self._context = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH)
self._context.verify_mode = ssl.CERT_REQUIRED
self._context.load_cert_chain(self.server_cert, self.server_key)
self._context.load_verify_locations(self.client_cert)
self.sock = None
and a couple of small changes to remove the certificate related functionality, everything seemed to work, the client could send messages to the server and the server could respond (and the client displayed the response).
When however I added the context related certificates I start getting the error:
An operation was attempted on something that is not a socket
The server waits at:
Client, addr = self.sock.accept()
and continues to run once the client has called (in the client.py file):
self._ssock.connect((HOST, PORT))
The server then reaches the lines:
def threaded_client(self, conn: socket):
conn.send(str.encode('Welcome to the Server'))
where it fails on this error.
Printing the terminal, a traceback and exception error results in:
Socket successfully created
Waiting for a Connection..
Connected to: 127.0.0.1:57434
Thread Number: 1
Traceback (most recent call last):
File "c:\testcode\Server.py", line 71, in threaded_client
conn.send(str.encode('Welcome to the Server'))
OSError: [WinError 10038] An operation was attempted on something that is not a socket
My knowledge is limited and I cannot find more examples of secure multi threaded two way communication client to server socket code. The idea is to ensure the client is authorized to communicate with the server before transmission happens.
Any ideas on where I am failing?
Thanks
Ok, It seems like I was close, but had a couple of tweaks to do.
The solution of:
SSL/TLS client certificate verification with Python v3.4+ SSLContext
and the commenters here, helped me get over the finish line.
Server code:
import socket
import os
from socket import AF_INET, SOCK_STREAM, SO_REUSEADDR, SOL_SOCKET, SHUT_RDWR
import ssl
from os import path
from _thread import *
import struct # Here to convert Python data types into byte streams (in string) and back
import traceback
# ---- To Avoid Message Boundary Problem on top of TCP protocol ----
def send_msg(sock: socket, msg): # ---- Use this to send
# Prefix each message with a 4-byte length (network byte order)
msg = struct.pack('>I', len(msg)) + msg
sock.sendall(msg)
def recv_msg(sock: socket): # ---- Use this to receive
# Read message length and unpack it into an integer
raw_msglen = recvall(sock, 4)
if not raw_msglen:
return None
msglen = struct.unpack('>I', raw_msglen)[0]
# Read the message data
return recvall(sock, msglen)
def recvall(sock: socket, n: int):
# Helper function to receive n bytes or return None if EOF is hit
try:
data = bytearray()
while len(data) < n:
packet = sock.recv(n - len(data))
if not packet:
return None
data.extend(packet)
return data
except Exception as e:
print("Exception in recvall : " + str(e))
# ---- Server Communication Setup
class Server:
def __init__(self):
self.HOST = '127.0.0.1' # Standard loopback interface address (localhost)
self.PORT = 65416 # Port to listen on (non-privileged ports are > 1023)
self.ThreadCount = 0
self.server_cert = path.join(path.dirname(__file__), "server.crt")
self.server_key = path.join(path.dirname(__file__), "server.key")
self.client_cert = path.join(path.dirname(__file__), "client.crt")
self._context = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH)
self._context.verify_mode = ssl.CERT_REQUIRED
self._context.load_cert_chain(certfile=self.server_cert, keyfile=self.server_key)
self._context.load_verify_locations(cafile=self.client_cert)
self.sock = None
def connect(self):
try: # create socket
self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM, 0) ###<-- socket.socket() ???
print ("Socket successfully created")
except socket.error as err:
print ("socket creation failed with error %s" %(err))
try: # bind socket to an address
self.sock.bind((self.HOST, self.PORT))
except socket.error as e:
print(str(e))
print('Waiting for a Connection..')
self.sock.listen(3)
def threaded_client(self, conn: socket):
try:
conn.send(str.encode('Welcome to the Server'))
while True:
data = recv_msg(conn)
print("data")
print(data)
if data is not None:
reply = 'Server Says: ' + data.decode('utf-8')
if not data:
break
send_msg(conn, str.encode(reply))
except Exception as e:
print(traceback.format_exc())
print(str(e))
finally:
print("Closing connection")
conn.shutdown(socket.SHUT_RDWR)
conn.close()
#conn.close()
def waitforconnection(self):
while True:
Client, addr = self.sock.accept()
conn = self._context.wrap_socket(Client, server_side=True)
print('Connected to: ' + addr[0] + ':' + str(addr[1]))
print("SSL established. Peer: {}".format(conn.getpeercert()))
start_new_thread(self.threaded_client, (conn, )) # Calling threaded_client() on a new thread
self.ThreadCount += 1
print('Thread Number: ' + str(self.ThreadCount))
#self.sock.close()
server = Server()
server.connect()
server.waitforconnection()
Client code:
import socket
import struct # Here to convert Python data types into byte streams (in string) and back
import sys
import ssl
import socket
import selectors
import types
import io
import os
import time
import requests
from pathlib import Path
import mysql.connector as mysql
from loguru import logger as log
from utils.misc import read_py_config
import json
import rsa
import base64
class Client:
def __init__(self):
self.host, self.port = "127.0.0.1", 65416
self.client_cert = os.path.join(os.path.dirname(__file__), "client.crt")
self.client_key = os.path.join(os.path.dirname(__file__), "client.key")
self.server_crt = os.path.join(os.path.dirname(__file__), "server.crt")
self.sni_hostname = "example.com"
self._context = ssl.create_default_context(ssl.Purpose.SERVER_AUTH, cafile=self.server_crt)
self._context.load_cert_chain(certfile=self.client_cert, keyfile=self.client_key)
self._sock = None
self._ssock = None
def checkvalidclient(self):
# ---- Client Communication Setup ----
HOST = self.host # The server's hostname or IP address
PORT = self.port # The port used by the server
try:
self._sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self._ssock = self._context.wrap_socket(self._sock, server_side=False, server_hostname=self.sni_hostname)
self._ssock.connect((HOST, PORT))
print ("Socket successfully created")
except socket.error as err:
print ("socket creation failed with error %s" %(err))
print('Waiting for connection')
Response = self._ssock.recv(1024)
if Response is not None:
print(Response.decode('utf-8'))
while True:
Input = input('Say Something: ')
send_msg(self._ssock, str.encode(Input))
Response = recv_msg(self._ssock)
if Response is not None:
print(Response.decode('utf-8'))
def closesockconnection(self):
self._ssock.close()
# ---- To Avoid Message Boundary Problem on top of TCP protocol ----
def send_msg(sock: socket, msg): # ---- Use this to send
# Prefix each message with a 4-byte length (network byte order)
msg = struct.pack('>I', len(msg)) + msg
sock.sendall(msg)
def recv_msg(sock: socket): # ---- Use this to receive
# Read message length and unpack it into an integer
raw_msglen = recvall(sock, 4)
if not raw_msglen:
return None
msglen = struct.unpack('>I', raw_msglen)[0]
# Read the message data
return recvall(sock, msglen)
def recvall(sock: socket, n: int):
# Helper function to receive n bytes or return None if EOF is hit
data = bytearray()
while len(data) < n:
packet = sock.recv(n - len(data))
if not packet:
return None
data.extend(packet)
return data
Also ensure (as per the link) that the certificate creation is correct.
There is also another useful link at:
Exploring HTTPS With Python
Which covers HTTPS, specifically the Wireshark section allows you to monitor the traffic from client to server. After completing the above and deploying Wireshark I see that the data is encrypted. Any editing of the certificates (manually) causes the app to fail.
There still needs to be additions of try and except if the communication is halted midway etc. But hoping it will smooth the journey for others.
Thanks to the commenters, helped lead me on the way to solution.
I am sending ssh count data from 'alphaclient' to 'alphaserver'. However the alphaclient server is not able to connect with alphaserver. Kindly help me resolve this error. I tried to kill the process at the port and restart the VMs but still getting the same issue.
This is the error output in alphaclient:
Traceback (most recent call last):
File "//./sshlogin-counter/alphaclient.py", line 82, in <module>
inform_alphaserver(client_message)
File "//./sshlogin-counter/alphaclient.py", line 45, in inform_alphaserver
c.connect((alphaserver_ip,port))
ConnectionRefusedError: [Errno 111] Connection refused
and this is the output in alphaserver:
Binding alphaserver at port 7888
Server Socket created.
Server socket binded at port 7888
Listening to port...
alphaclient.py
import os
import socket
input_file = os.path.join('/','var', 'log', 'auth.log')
#output_file = os.path.join('.','sshlogin-counter','client_message.txt')
total_ssh_attempts = 0
#Function1 that reads /var/log/auth.log and returns total ssh attempts made into that VM
def ssh_attempts(input_file):
successful_ssh_attempts = 0
invalid_ssh_attempts = 0
current_ssh_attempts = 0
with open(input_file,'r') as f:
f = f.readlines() #list of lines
for line in f:
if 'sshd' and 'Accepted publickey' in line:
successful_ssh_attempts+=1
#elif 'sshd' and 'Invalid user' in line:
#invalid_ssh_attempts+=1
current_ssh_attempts = successful_ssh_attempts + invalid_ssh_attempts
return (current_ssh_attempts)
#Function2 that informs Alphaserver of new ssh login attempts
def inform_alphaserver(client_message):
port = 7888
alphaserver_hostname = socket.gethostname()
alphaserver_ip = socket.gethostbyname(alphaserver_hostname)
print('Establishing connection with {} at port {} ...'.format(alphaserver_ip,port))
c = socket.socket()
print('Client socket created...')
c.connect((alphaserver_ip,port))
print('Client socket connected with {} at port {}'.format(alphaserver_ip, port))
client_message = client_message.encode()
print("Sending client message...")
c.send(client_message)
print("Message has been transmitted to alphaserver successfully")
c.close()
print("Connection Closed!!!")
#Monitor new ssh login attempts
while True:
#Function 1
current_ssh_attempts = ssh_attempts(input_file)
#Condition to test if new login attempts made
if current_ssh_attempts > total_ssh_attempts:
total_ssh_attempts = current_ssh_attempts
print('SSH login attempts detected!!!')
client_message = '{} had {} attempt'.format(socket.gethostname(), total_ssh_attempts)
#Function 2
#Send output file to Alphaserver
inform_alphaserver(client_message)
alphaserver.py
import os
import socket
#File for storing messages from Alphaclient
client_messages = os.path.join ('.','sshlogin-counter','client_messages.txt')
#Function that listens to client servers and receives client data
def receive_clientmessage():
port = 7888
host = socket.gethostname()
print('Binding {} at port {}'.format(host,port))
s = socket.socket()
print('Server Socket created.')
s.bind((host, port))
print('Server socket binded at port {}'.format(port))
s.listen(2)
print('Listening to port...')
while True:
c , addr = s.accept()
print("Connected with {}".format(addr))
client_message = c.recv(1024).decode()
client_hostname = list(str(client_message).split(" "))[0] #str converted to list and list[0] is the client_hostname
print("Client host name is {} ".format(client_hostname))
c.close()
break
#s.close()
return (client_hostname, client_message)
#Function to write client data to client_message.
def update_client_messages(client_hostname, client_message):
file = open(client_messages, 'r+')
f = file.read()
if client_hostname in f:
position = f.index(client_hostname)
file.seek(position)
file.write(str(client_message))
print('Updated client SSH login data')
file.close()
else:
file = open(client_messages,'a')
file.write('\n'+ str(client_message))
print('Added new client SSH login data')
file.close()
#Continuosly monitor and display client data
while True:
client_hostname, client_message = receive_clientmessage()
update_client_messages(client_hostname, client_message)
file = open(client_messages)
content = file.read()
print('----------------------------------------------------')
print(content)
print('----------------------------------------------------')
file.close()
I'm trying to create an online code to a game I'm making. Obviously, running this code gives an error. The error is [WinError 10053] An established connection was aborted by the software in your host machine.
Here's my code:
SERVER
from _thread import *
import sys
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
host = socket.gethostname()
server = 'localhost'
port = 5555
server_ip = socket.gethostbyname(server)
try:
s.bind((server, port))
except socket.error as e:
print(str(e))
s.listen(2)
print("Currently waiting for other users...")
currentId = "0"
pos = ["0:50,50", "1:100,100"]
def threaded_client(conn):
global currentId, pos
conn.send(str.encode(currentId))
currentId = "1"
reply = ''
while True:
try:
data = conn.recv(2048)
reply = data.decode('utf-8')
if not data:
conn.send(str.encode("Goodbye"))
break
else:
print("Recieved: " + reply)
arr = reply.split(":")
id = int(arr[0])
pos[id] = reply
if id == 0: nid = 1
if id == 1: nid = 0
reply = pos[nid][:]
print("Sending: " + reply)
conn.sendall(str.encode(reply))
except:
break
print("Connection Closed")
conn.close()
while True:
conn, addr = s.accept()
start_new_thread(threaded_client, (conn,))
CLIENT
import time
class Network:
def __init__(self):
randomvar = "."
while True:
try:
self.client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.host = "localhost" # For this to work on your machine this must be equal to the ipv4 address of the machine running the server
# You can find this address by typing ipconfig in CMD and copying the ipv4 address. Again this must be the servers
# ipv4 address. This feild will be the same for all your clients.
self.port = 5555
self.addr = (self.host, self.port)
self.id = self.connect()
break
except ConnectionRefusedError:
if randomvar != "Waiting for server...":
print("Waiting for server...")
randomvar = "Waiting for server..."
def getNumber(self):
pass
def connect(self):
self.client.connect(self.addr)
return self.client.recv(2048).decode()
def send(self, data):
"""
:param data: str
:return: str
"""
try:
self.client.send(str.encode(data))
reply = self.client.recv(2048).decode()
return reply
except socket.error as e:
return str(e)
n = Network()
print(n.send("Host"))
print(n.send("hello"))
On the server, the only things it receives Host, but not hello. That's where I get the error, but It won't tell me which line it is.
Any help?
You are ignoring the exception. Instead, print it out to get an idea of what is wrong:
Traceback (most recent call last):
File "D:\temp\python\server.py", line 39, in threaded_client
id = int(arr[0])
ValueError: invalid literal for int() with base 10: 'Host'
This leads to this line:
id = int(arr[0])
It looks like the server is expecting the messages to be in the form of id:msg but the client is not sending that. It is just sending the message without an id. You can check this in the server.
arr = reply.split(":")
if len(arr) != 2 or !arr[0].isdigit():
# Handle error....
When closing the connection, you are likely forgetting to close both sides.
I was able to modify your code to fit the scenario from this post which explains the root cause of [WinError 10053] An established connection was aborted by the software in your host machine, which lies in the WSAECONNABORTED error from WinSock, the windows sockets api
I made a more detailed answer about this on this SO post.
import socket
MAX_BUFFER_SIZE = 4096
class ClientSocket:
def __init__(self):
print("Client socket started....")
self.soc = None
def send_to_Server(self, data):
print('Time to send data to Server..... %s', data)
self.soc.send(data.encode("utf8"))
def receive_from_Server(self):
print('Time to receive from Server.....')
result_bytes = self.soc.recv(MAX_BUFFER_SIZE)
result_string = result_bytes.decode("utf8")
print("Result from server is {}".format(result_string))
def start_client(self):
self.soc = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.soc.connect(("localhost", 8000))
print('Client connected....')
husainshoab#hs-Len:~$ python IOTDeviceSocket.py
Traceback (most recent call last):
File "IOTDeviceSocket.py", line 7, in
class ClientSocket:
File "IOTDeviceSocket.py", line 11, in ClientSocket
self.soc = None
NameError: name 'self' is not defined
There appears to be nothing wrong with your code. I just used it to create a simple test application
# ClientSocket.py
import socket
MAX_BUFFER_SIZE = 4096
class ClientSocket:
def __init__(self):
print("Client socket started....")
self.soc = None
def send_to_Server(self, data):
print('Time to send data to Server..... %s', data)
self.soc.send(data.encode("utf8"))
def receive_from_Server(self):
print('Time to receive from Server.....')
result_bytes = self.soc.recv(MAX_BUFFER_SIZE)
result_string = result_bytes.decode("utf8")
print("Result from server is {}".format(result_string))
def start_client(self):
self.soc = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.soc.connect(("localhost", 8000))
print('Client connected....')
cs = ClientSocket()
cs.start_client()
cs.send_to_Server('Hello')
cs.receive_from_Server()
here's a simple test server which just spits back some JSON data
# test_server.py
import socket
from datetime import datetime
import json
def logMessage(clientMessage):
logTime = datetime.today();
msg = "{} | {}\n".format(logTime, clientMessage)
print msg
TCP_PORT = 8000
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind(('localhost', TCP_PORT))
# listen() puts the socket into server mode,
server.listen(1)
while True:
# wait for an incoming connection
connection, address = server.accept()
try:
# receive data in chunks of 64 bytes
while True:
data = connection.recv(64)
# how do we know if we received all the data?
if data:
# we received data from the client, log it to the file
logMessage(data)
response = {
'name' : 'Jonathan Swift',
'occupation' : 'author'
}
jsonResponse = json.dumps(response)
messageLength = len(jsonResponse)
bytesSent = 0
# send a response to the client after turning our dict into
# a JSON string
while(bytesSent < messageLength):
sent = connection.send(jsonResponse)
bytesSent += sent
else:
# no data, break out of receiving loop
break
except Exception as e:
raise
finally:
connection.close()
import socket
MAX_BUFFER_SIZE = 4096
class ClientSocket:
soc = None
def __init__(self):
print("Client socket started....")
self.soc = None
def send_to_Server(self, data):
print('Time to send data to Server..... %s', data)
self.soc.send(data.encode("utf8"))
def receive_from_Server(self):
print('Time to receive from Server.....')
result_bytes = self.soc.recv(MAX_BUFFER_SIZE)
result_string = result_bytes.decode("utf8")
print("Result from server is {}".format(result_string))
def start_client(self):
self.soc = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.soc.connect(("localhost", 8000))
print('Client connected....')
you should define the soc variable after class statement so that you can use it globally.
from socket import *
import thread
def thread_handler(connectionSocket, addr):
while True:
# Establish the connection
print ("Ready to serve...")
# connectionSocket, addr = serverSocket.accept()
try:
message = connectionSocket.recv(1024)
# print(message, '::', message.split()[0], ":", message.split()[1])
filename = message.split()[1]
# print(filename, "||", filename[1:])
f = open(filename[1:], "r")
outputdata = f.read()
# print(outputdata)
#Send one HTTP header line into socket
#Fill in start
connectionSocket.send('\nHTTP/1.1 200 OK\n\n')
connectionSocket.send(outputdata)
#Fill in end
#Send the content of the requested file to the client
for i in range(0,len(outputdata)):
connectionSocket.send(outputdata[i:i+1])
connectionSocket.send(b'\r\n\r\n')
except IOError:
#Send response message for file not found
#Fill in Start
connectionSocket.send('\nHTTP/1.1 404 Not Found\n\n')
#Fill in end
#Close client socket
if __name__ == '__main__':
serverSocket = socket(AF_INET, SOCK_STREAM)
# Prepare a sever socket
serverSocket.bind(("localhost", 6789))
serverSocket.listen(1)
while True:
print('waiting for connection...')
connectionSocket, addr = serverSocket.accept()
print('...connected from:', addr)
thread.start_new_thread(thread_handler, (connectionSocket, addr))
serverSocket.close()
I understand how the multi threading works now, but I could not figure out how to build a connection.
I'm trying to do a multi-threaded version of TCP server. However, it keeps giving "list index out of range":
Ready to serve...
Unhandled exception in thread started by <function thread_handler at 0x10b9750c8>
Traceback (most recent call last):
File "http_server_multi.py", line 16, in thread_handler
filename = message.split()[1]
IndexError: list index out of range
If nothing is received from the socket because there is no data yet, the split() will return [''] with only on item and the [1] on it will fail.
Try to add this before the failing line
if not message:
# time.sleep(0.01)
continue
The sleep() call will prevent the thread to use too much CPU, you can umcomment it and adapt the value to your needs.