0% found this document useful (0 votes)
0 views

C8+Socket+Programming

The document provides a comprehensive overview of socket programming, detailing how programs communicate through sockets using TCP/IP protocol. It includes code examples for creating servers and clients, handling messages, and implementing bi-directional communication, as well as projects and assignments to reinforce learning. Additionally, it discusses encoding and decoding data, the importance of protocols, and iterative server design.

Uploaded by

Alex?
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
0 views

C8+Socket+Programming

The document provides a comprehensive overview of socket programming, detailing how programs communicate through sockets using TCP/IP protocol. It includes code examples for creating servers and clients, handling messages, and implementing bi-directional communication, as well as projects and assignments to reinforce learning. Additionally, it discusses encoding and decoding data, the importance of protocols, and iterative server design.

Uploaded by

Alex?
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 55

H2 Computing 1

C8 Socket Programming
C8 Socket Programming 2

How programs communicate?


C8 Socket Programming 3

What is a Socket?
A socket connection is like a bi-directional communication pipe
between two running programs.

The Internet Socket, which is most common, uses the TCP/IP *


protocol so that computers can access each other even over the
network.
* Transmission Control Protocol and Internet Protocol

Computer X Computer Y

Program A Program B
bytes
bytes

Internet
Socket
C8 Socket Programming 4

For simplicity, we illustrate an Internet Socket as a pipe


connecting the two computers.

In reality, data communication between two computers passes


through multiple devices before reaching its destination.

Computer X Computer Y

Program A Program B

device
bytes bytes bytes
bytes
device bytes bytes
C8 Socket Programming 5

Create a server listening for client


from socket import *

my_socket = socket()
my_socket.bind(('127.0.0.1', 12345))
my_socket.listen()
server.py

Computer X

Listening …
These 4 lines of code
Program A are essential to
initialise my_socket()

my_socket

Server
127.0.0.1:12345
C8 Socket Programming 6

Connecting a client to the server


from socket import *
my_socket = socket()

addr=input('Enter IPv4 address of server: ')


port=int(input('Enter port number of server: '))
client.py

my_socket.connect((addr, port)) Computer Y

Program B
Server Port Port
127.0.0.1 12345 5000

Socket

my_socket Client
192.0.0.1:5000
C8 Socket Programming 7

Server accepts the client


new_socket, addr = my_socket.accept()
Print('Connected to: ' + str(addr))

new_socket my_socket my_socket

Computer X Computer Y
server.py

Listening …
Program A Program B

Port Port
Accepted !
12345 5000

Socket

Server Client
127.0.0.1:12345 192.0.0.1:5000
The socket.accept() method will block the program until a new client
connects; then it will create a new_socket with the client's address.
C8 Socket Programming 8

Server sends a message


Computer X Computer Y

Listening …
Program A Program B

Msg bytes Msg


Socket

Server Client
127.0.0.1:12345 192.0.0.1:5000
server.py

Bufsize(byte): max amount


Msg = 'Hello from server' of data to be received at
once. Should be small
new_socket.sendall(Msg.encode()) power of 2, eg 210

client.py
Msg = my_socket.recv(1024)
Print(Msg.decode())
C8 Socket Programming 9

Closing all the sockets


new_socket my_socket my_socket
Computer X Computer Y

Listening …
Program A Program B

Socket

Server Client
127.0.0.1:12345 192.0.0.1:5000
server.py

new_socket.close()
my_socket.close()

client.py
my_socket.close()
C8 Socket Programming 10

Unicode and Encodings


C8 Socket Programming 11

Python's Bytes Type


Sockets work at a very basic level, they can only send and receive
data in the form of raw bytes.
ie. data is encoded into a sequence of 8-bit characters.

msg = 'string'.encode()
type(msg) → <class 'bytes'>
msg → b'string'
len(msg) → 6 which is same as len('string')

print(msg.decode()) → 'string'

Message need to be encoded before sending and


be decoded after receiving.
C8 Socket Programming 12

Python's Bytes Type


The Chinese character 中 can be written as the str literal
'\u4e2d' in Python. The use of the escape code '\u' to
produce the character by specifying its Unicode code point.
Encode
msg1 = '\u4e2d' before sending
type(msg1) → <class 'str'>
len(msg1) → 1 msg2 = msg1.encode()
print(msg1) → 中
type(msg2) → <class 'bytes'>
len(msg2) → 3 in UTF-8
print(msg2) → b'\xe4\xb8\xad'

msg3 = msg2.decode()
type(msg3) → <class 'str'>
Decode
len(msg3) → 1
print(msg3) → 中 after receiving
C8 Socket Programming 13

Project 1
Single direction Server-Client communication
C8 Socket Programming 14

from socket import *

my_socket = socket()
my_socket.bind(('127.0.0.1', 12345))
my_socket.listen()
server.py

new_socket, addr = my_socket.accept()


print('Connected to: ' + str(addr))
Msg = 'Hello from server\n'
new_socket.sendall(Msg.encode())

new_socket.close()
my_socket.close()
C8 Socket Programming 15

from socket import *

my_socket = socket()

addr=input('Enter IPv4 address of server: ')


port=int(input('Enter port number of server: '))
client.py

my_socket.connect((addr, port))

Msg = my_socket.recv(1024)
print(Msg.decode())

my_socket.close()
16

Assignment 1
Single direction communication from 1 Server to 2 Clients
C8 Socket Programming 17

Modify the server.py in Project 1 so that the server can


communicate with two clients.
from socket import *

my_socket = socket()
my_socket.bind(('127.0.0.1', 12345))
my_socket.listen()
server.py

new_socket, addr = my_socket.accept()


print('Connected to: ' + str(addr))
Msg = 'Hello from server\n'
new_socket.sendall(Msg.encode())

new_socket.close()
my_socket.close()
C8 Socket Programming 18

Same as client.py in Project 1:

from socket import *

my_socket = socket()

addr=input('Enter IPv4 address of server: ')


client1.py

port=int(input('Enter port number of server: '))

my_socket.connect((addr, port))
Msg = my_socket.recv(1024)
print(Msg.decode())

my_socket.close()
C8 Socket Programming 19

Same as client.py in Project 1:

from socket import *

my_socket = socket()

addr=input('Enter IPv4 address of server: ')


client2.py

port=int(input('Enter port number of server: '))

my_socket.connect((addr, port))
Msg = my_socket.recv(1024)
print(Msg.decode())

my_socket.close()
C8 Socket Programming 20

Project 2
Designing a Protocol
C8 Socket Programming 21

Why do we need a Protocol?


When a server send a long sequence of bytes, some of the data
packet may be delayed during transportation through the
network.

To understand this, we will break the data in to two sequences.


After sending out the first piece of data, we call the sleep()
method in the time module to simulate a delay in the busy
network, then call socket.sendall() again to send the
second piece of data.
C8 Socket Programming 22

from socket import *


from time import *

my_socket = socket()
my_socket.bind(('127.0.0.1', 12345))
my_socket.listen()
server.py

new_socket, addr = my_socket.accept()


print('Connected to: ' + str(addr))

new_socket.sendall(b'Hello fr')
sleep(0.1)
new_socket.sendall(b'om server\n')

new_socket.close()
my_socket.close()
C8 Socket Programming 23

Run the client.py from Project 1 to receive the message


from the server.

from socket import *


client.py

my_socket = socket()
my_socket.connect(('127.0.0.1', 12345))

print(my_socket.recv(1024).decode())
[Project 1]

my_socket.close()

In this example, the client receives only the first part of the data
and closes the socket. This will produce an error when the server
tries to send the second piece of data.
In general, we should never assume that socket.recv()
has received all the bytes that were sent.
C8 Socket Programming 24

We can agree on a protocol beforehand that any data we


transmit will always end with a newline character \n and that
the data itself will never contain the \n character.
The following client.py search for the \n character to
detect the end of a transmission:

from socket import *


my_socket = socket()
my_socket.connect(('127.0.0.1', 12345))
client.py

data = b''
while b'\n' not in data:
data += my_socket.recv(1024)
print(data.decode())
We will use this method whenever
my_socket.close()
we need to receive any data.
C8 Socket Programming 25

Assignment 2
Bi-direction Server-Client communication
C8 Socket Programming 26

Assignment 2 :

Modify the server.py and client.py (with protocol),


given in the next two slides, so that it will be a bi-directional
communication between the server and the client.
C8 Socket Programming 27

from socket import *

my_socket = socket()
my_socket.bind(('127.0.0.1', 12345))
my_socket.listen()
server.py

new_socket, addr = my_socket.accept()


print('Connected to: ' + str(addr))

new_socket.sendall(b'Hello from server\n')

new_socket.close()
my_socket.close()
C8 Socket Programming 28

from socket import *

my_socket = socket()
my_socket.connect(('127.0.0.1', 12345))
client.py (with protocol)

data = b''
while b'\n' not in data:
data += my_socket.recv(1024)
print(data.decode())

my_socket.close()
C8 Socket Programming 29

Project 3
Iterative Server
C8 Socket Programming 30

Why we need a iterative server?


Currently, the server program exits immediately after it finishes
working with a client. In reality, the server program should run
continuously and is always listening for the clients' connection
requests.
Must include the 4 essential lines
... of code to initialise my_socket()
while True:
print('Type Ctrl-F6 or close the shell
to terminate the server.')
server.py

new_socket, addr = my_socket.accept()


print('Connected to: ' + str(addr))
new_socket.sendall(b'Hello from server\n')
new_socket.close()
my_socket.close()
Iterative servers are easy to write, but they are limited and can
only handle one client at a time.
C8 Socket Programming 31

Run the client.py from Project 2 to receive the message


from the server.

from socket import *

my_socket = socket()
client.py (with protocol)

my_socket.connect(('127.0.0.1', 12345))

data = b''
while b'\n' not in data:
data += my_socket.recv(1024)
print(data.decode())

my_socket.close()

Since the server is still running, you may execute the client
program again, a few more times, after it closes my_socket.
C8 Socket Programming 32

Project 4
A Chat Program
C8 Socket Programming 33

Must include the 4 essential lines


... of code to initialise my_socket()
print('Type Ctrl-F6 or close the shell to
terminate the server.')
chat_socket, addr = my_socket.accept()
print('Connected to: ' + str(addr)) Sending
while True:
data = input('Input message: ').encode()
chat_socket.sendall(data + b'\n')
server.py

print('WAITING FOR CLIENT ...')


data = b''
while b'\n' not in data:
data += chat_socket.recv(1024)
print('Client wrote: ' + data.decode())
chat_socket.close()
my_socket.close() Receiving
C8 Socket Programming 34

The client program is similar, except the order of sending and


receiving is reversed.

from socket import *


chat_socket = socket()
chat_socket.connect(('127.0.0.1', 12345))
Receiving
while True:
client.py

print('WAITING FOR SERVER ...')


data = b''
while b'\n' not in data:
data += chat_socket.recv(1024)
print('Server wrote: ' + data.decode())
data = input('Input message: ').encode()
chat_socket.sendall(data + b'\n')

chat_socket.close() Sending
C8 Socket Programming 35

Assignment 3
A Chat Program with Quit
C8 Socket Programming 36

Assignment 3 : Chat program with Quit


Currently, there is no way to exit our chat programs other than
using the Ctrl-F6 or closing the IDLE shell.

Modify the chat_client.py and chat_server.py so that


both programs exit once the word 'BYE' * is mentioned by either
user. Remember to close all the sockets before exiting.

* The user may use both small or capital letters.


C8 Socket Programming 37

Project 5
A Turn-Based Game – "Guess Head or Tail"
C8 Socket Programming 38

Consider the following 'Guess Head or Tail' game:

from random import *


def game(guess):
if guess == 'H' or guess == 'T':
if guess == choice(['H', 'T']):
head_tail.py

return 'You are right!'


else:
return 'Sorry, you are wrong.'
elif guess == 'Q':
return 'Thanks for playing the game. Bye!'
else:
return 'Invalid entry. Try again.'
C8 Socket Programming 39

def main():

while True:
guess = input('\n\nI will toss a coin, \
head_tail.py

enter H or T for guessing a \


head or tail (T), and Q to \
quit: ').upper()

print(game(guess))

if guess == 'Q':
break

Copy the codes for game() and main() and save them in the
head_tail.py program. Run the program and play the game.
Observe how the game is being implemented.
C8 Socket Programming 40

from socket import * Must include the program


code for game(guess)
my_socket = socket()
my_socket.bind(('127.0.0.1', 12345))
my_socket.listen()

print('Type Ctrl-F6 or close the shell to \


server.py

terminate the server.')


new_socket, addr = my_socket.accept()
print('Connected to: ' + str(addr))

while True: Convert the code for main()


and include it here

new_socket.close()
my_socket.close()
C8 Socket Programming 41

Observe how the following server


program communicate with the client.
while True:
new_socket.sendall(b'I will toss a coin, \
guess if it is a head (H) or tail (T) : ')

client_guess = b''
server.py

while b'\n' not in client_guess:


client_guess += new_socket.recv(1024)
client_guess = client_guess.decode().strip()

new_socket.sendall(game(client_guess)\
.encode() + b'\n')
if client_guess == 'Q':
break
C8 Socket Programming 42

from socket import *


my_socket = socket()
my_socket.connect(('127.0.0.1', 12345))

while True:
data = my_socket.recv(1024)
guess = input(data.decode()).upper()
my_socket.sendall(guess.encode() + b'\n')
client.py

data = b''
Send user's input to the server
while b'\n' not in data:
data += my_socket.recv(1024)
print(data.decode())

if guess == 'Q':
Display message from the server
break

my_socket.close()
C8 Socket Programming 43

Assignment 4
A Turn-Based Game – "Guess Head or Tail" with Counters
C8 Socket Programming 44

Assignment 4 : Add Counters to the


"Guess Head or Tail" game
N = Total number of guesses
C = Total number of correct guesses

Modify the server and client program to display the following when
the user ended the game:

' You have guessed correctly C out of N times.'


C8 Socket Programming 45

Assignment 5
A Turn-Based Game – "Guess High or Low"
C8 Socket Programming 46

Assignment 5 : Write the server program

1. Study the "Guess High or Low" game.


2. Use, but do not modify, the provided client program.
3. Using the template for the server program, write the necessary
code to communicate with the client program for the game.
C8 Socket Programming 47

Consider the following 'Guess High or Low' game:

from random import *

num = randint(1,100)
def game(guess):
if guess.isdigit():
high_low.py

if int(guess) == num:
return 'You win!'
elif int(guess) > num:
return 'HIGH'
else:
return 'LOW'
else:
return 'Please enter number 1 to 100'
C8 Socket Programming 48

def main():
counter = 5
while counter > 0:
guess = input('Guess a number 1 to 100: ')
if game(guess) == 'You win!':
high_low.py

print(game(guess))
break
else:
print(game(guess))
counter -= 1
if counter == 0:
print('You ran out of tries! Game over.')

Copy the codes for game() and main() and save them in
the high_low.py program. Run the program and play the
game. Observe how the game is being implemented.
C8 Socket Programming 49

from socket import *


s = socket()
s.connect(('127.0.0.1', 12345))
Do not modify the
client program.
while True:
data = b''
while b'\n' not in data:
data += s.recv(1024)
received = data.decode().strip()
if received == 'LOW':
client.py

print('Your guess is too low.')


elif received == 'HIGH':
print('Your guess is too high.')
elif received == 'GUESS':
guess = input('Enter guess (1-100): ')
s.sendall(guess.encode() + b'\n')
elif received == 'WIN':
print('You win!')
break
elif received == 'GAMEOVER':
print('You ran out of tries! Game over.')
break

s.close()
C8 Socket Programming 50

from socket import * Must include the program code for


game(guess) and the random value num
my_socket = socket()
my_socket.bind(('127.0.0.1', 12345))
my_socket.listen()
(template) server.py

print('Type Ctrl-F6 or close the shell to \


terminate the server.')
new_socket, addr = my_socket.accept()
print('Connected to: ' + str(addr))

while True: Write the code and


include it here

new_socket.close()
my_socket.close()
C8 Socket Programming 51

Assignment 6
Symmetrical Game – "Scissor, Paper, Stone"
C8 Socket Programming 52

Assignment 6 :

1. The provided “scissor-paper-stone" program code is for a player


to play against the computer "Robot".
2. Modify the program code so that it becomes a symmetrical
game where a human "Player1" plays against another human
"Player2".
3. Write the server (as "Player2") and client (as "Player1") program
codes for the symmetrical game.
C8 Socket Programming 53

Consider the following 'Scissor, Paper, Stone' game:

# player1 is a human # player2 is a robot

from random import *


scissor-paper-stone.py

def game(opponent):
player2 = choice(['Scissor', 'Paper', 'Stone'])
print('Player2: ', player2)
if player2 == opponent:
return 'Draw'
elif (player2 == 'Scissor' and opponent == \
'Paper') or (player2 == 'Paper' and opponent == \
'Stone') or (player2 == 'Stone' and opponent == \
'Scissor'):
return 'Player2 wins!'
else:
return 'Player1 wins!'
C8 Socket Programming 54

def main():
print('You are Player1 playing against Player2')
counter = 3
d = {'1':'Scissor', '2':'Paper', '3':'Stone'}
scissor-paper-stone.py

while counter > 0:


player1 = input('Player1: Enter (1)Scissor,\
(2)Paper or (3)Stone : ')
if player1 in d:
print('Player1: ', d[player1])
print(game(d[player1]))
counter -= 1
else:
print('Please enter only 1, 2 or 3.')
Copy the codes for game() and main() and save them in
the scissor-paper-stone.py program.
Run the program and play the game. Observe how the game is
being implemented.
55

The End
Socket Programming

You might also like