client and server

0 comments

Client

from socket import *

import sys

import struct

# helper functions to create messages and to split messages

def createMessage(seq, msg):

    return str(seq) + “@” + msg

def splitMessage(input):

    return (input[:input.find(‘@’)], input[input.find(‘@’)+1:])

# Get the server hostname and port as command line arguments

argv = sys.argv                     

if len(argv ) != 3:

    print(“Incorrect number of command-line arguments”)

    print(“Invoke client with: python”, argv[0], “<MulticastIP> <port>”)

    exit()

host = argv[1]

port = int(argv[2])

clientSocket = socket(AF_INET, SOCK_DGRAM)

# Set socket timeout as 1 second

clientSocket.settimeout(1)

# Set the time-to-live for messages to 1 so they do not go past the

# local network segment.

ttl = struct.pack(‘b’, 1)

clientSocket.setsockopt(IPPROTO_IP, IP_MULTICAST_TTL, ttl)

# we will get a (potentially) large number of replies for each request

# add a sequence number to the messages and read replies until we get

# to the first one with a new sequence number

msg_sequence = 0

while True:

    msg_sequence += 1

    message = createMessage(msg_sequence, input(“Next command: “))

    try:

        clientSocket.sendto(message.encode(), (host, port))

        reply, serverAddress = clientSocket.recvfrom(2048)

        (seq, reply) = splitMessage(reply.decode())

        while int(seq) < msg_sequence:

            # print(“Discard old reply”)

            reply, serverAddress = clientSocket.recvfrom(2048)

            (seq, reply) = splitMessage(reply.decode())

        print(reply)

        if reply == “bye”:

            break

    except:

        print(“Message to server timed out, please retry”)

# once we break out of the loop, close socket and terminate

clientSocket.close()

Server

from socket import *

import sys

import threading

import random

import time

import struct

# read in information one textfile, store and return as one long string

def readTextfile(filename):

    result = “”

    try:

        f = open(filename)

    except:

        print(“File “, filename, ” does not exist”)

        return “”

    for line in f:

        result = result + line

    return result

# write reservations textfile

def writeTextfile(filename, input):

    try:

        f = open(filename, “w”)

    except:

        print(“File “, filename, ” could not be opened for writing”)

        return

    for line in input:

        f.write(line + “\n”)

# check format of RESERVE and DELETE commands

def checkFormat(cmd_components):

    # check for sufficient fields

    if len(cmd_components) != 4:

        return “Inaccurate number of parameters”

    # check for valid input fields

    if cmd_components[1] not in rooms:

        return cmd_components[1] + ” not a valid room”

    if cmd_components[2] not in timeslots:

        return cmd_components[2] + ” not a valid timeslot”

    if cmd_components[3] not in days:

        return cmd_components[3] + ” not a valid day”

    # if we are here, everything worked out, return okay

    return “okay”

# process a single user command, returning either the result or an appropriate error message

def processCommand(cmd):

    global res

    if cmd == “days”:

        return days

    if cmd == “rooms”:

        return rooms

    if cmd == “timeslots”:

        return timeslots

    if cmd[:5] == “check”:

        specific_room = cmd[6:]

        if specific_room not in rooms:

            return “Room ” + specific_room + ” not a valid room”

        results = “”

        for r in res:

            components = r.split()

            if components[0] == specific_room:

                if not results == “”:

                    results = results + “\n”

                results = results + r

        if results == “”:

            results = “No room reservation found”

        return results

    if cmd[:7] == “reserve”:

        cmd_components = cmd.split()

        check_results = checkFormat(cmd_components)

        if not check_results == “okay”:

            return check_results

        # check whether reservation already exists

        found = False

        for r in res:

            components = r.split()

            if components[0] == cmd_components[1] and components[1] == cmd_components[2] and components[2] == cmd_components[3]:

                found = True

        if found:

            return “Reservation already exists”

        # once we are here, add reservation and return confirmation

        new_res = cmd_components[1] + ” ” + cmd_components[2] + ” ” + cmd_components[3]

        res.append(new_res)

        # save new reservations in textfile (i.e., stable storage)

        writeTextfile(“reservations.txt”, res)

        return “Reservation confirmed”

    if cmd[:6] == “delete”:

        cmd_components = cmd.split()

        check_results = checkFormat(cmd_components)

        if not check_results == “okay”:

            return check_results

        # iterate over all reservations, copy all the ones that are not involved to new_reservations

        found = False

        new_res = []

        for r in res:

            components = r.split()

            if components[0] == cmd_components[1] and components[1] == cmd_components[2] and components[2] == cmd_components[3]:

                found = True

            else:

                new_res.append(r)

        if not found:

            return “Reservation did not exist”

        # we had a proper deletion request, store this as the new set and return a deletion confirmation

        res = new_res

       # save new reservations in textfile (i.e., stable storage)

        writeTextfile(“reservations.txt”, res)

        return “Deletion confirmed”

    if cmd == “quit”:

        return “bye”

    # if we get here, the command is unknown, simply return error message

    return cmd + “: Command unknown”

# helper functions to create messages and to split messages

def createMessage(seq, msg):

    return str(seq) + “@” + msg

def splitMessage(input):

    return (input[:input.find(‘@’)], input[input.find(‘@’)+1:])

# create Threading class – one instance per launched threat, dealing with one user command

class ClientCmdThread(threading.Thread):

    def __init__(self, ip, port, msg):

        threading.Thread.__init__(self)

        self.ip = ip

        self.port = port

        message = msg.decode()

        (self.sequence_number, self.msg) = splitMessage(message)

    def run(self):

        print(“Start executing thread for:”, self.msg, “with sequence number”, self.sequence_number)

        answer = createMessage(self.sequence_number,processCommand(self.msg))

        serverSocket.sendto(answer.encode(), (self.ip, self.port))

        # Generate random number in the range of 2 to 4 and sleep

        rand = random.randint(5, 10)  

        time.sleep(rand)

        print(“End executing thread for:”, self.msg)

# Get the multicast group address and server port as command line arguments and set up the server socket

argv = sys.argv                     

if len(argv ) != 3:

    print(“Incorrect number of command-line arguments”)

    print(“Invoke server with: python”, argv[0], “<MulticastIP> <port>”)

    exit()

multicastGroup = argv[1]

serverPort = int(argv[2])

serverSocket = socket(AF_INET, SOCK_DGRAM)

# allow multiple server/receiver processes on the same computer to bind to the multicast port

#

# IMPORTANT

#

# Windows does not support SO_REUSEPORT, so we need to use REUSEADDR

#

# Linux/MacOS: need to use REUSEPORT

#

serverSocket.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)

# Bind to the server address: localhost and serverPort

serverSocket.bind((”, serverPort))

# Tell the operating system to add the socket to the multicast group

# on all interfaces.

group = inet_aton(multicastGroup)

mreq = struct.pack(‘4sL’, group, INADDR_ANY)

serverSocket.setsockopt(IPPROTO_IP, IP_ADD_MEMBERSHIP, mreq)

# read in the information in the four input textfiles

rooms = readTextfile(“rooms.txt”)

days = readTextfile(“days.txt”)

timeslots = readTextfile(“timeslots.txt”)

reservations = readTextfile(“reservations.txt”)

# split reservations into a list for easier handling later

res = reservations.splitlines()

print (“The server is ready to receive”)

# main server loop: receive a single datagram with a message/command and act on it

while True:

    message, (clientIP, clientPort) = serverSocket.recvfrom(2048)

    newClientThread = ClientCmdThread(clientIP, clientPort, message)

    newClientThread.start()

# once we break out of the loop, close socket and terminate

serverSocket.close()

print (“Shutting the server down”)

About the Author

Follow me


{"email":"Email address invalid","url":"Website address invalid","required":"Required field missing"}