Python Network Programming, socket module
ID Python Meetup, 23 Februari 2013
ID Python Meetup, 23 Februari 2013
Sakti Dwi Cahyono
webdev @ insan infonesia
github.com/sakti
@saktidc
Internet = Internetwork, interconnecting computer networks
Kumpulan protocol kumunikasi yang digunakan pada Internet atau network sejenis.
Protocol stack paling popular untuk wide area network.
Transmission Control Protocol (675, 793, 1122, 2581), Internet Protocol (ipv4: 791).
IPv4 menggunakan 32-bit untuk alamat IP.
$python -c "print '{0:,}'.format(2 ** 32)"
4,294,967,296
Sudah habis pada tanggal 3 Februari 2011.
32 bit
74.125.135.113
128 bit
2404:6800:4003:802::1007
16 bit unsigned integer (1 - 65535).
Well-known | 1 - 1023 |
Registered | 1024 - 49151 |
Dynamic | 49152 - 65535 |
$cat /etc/services
.
.
ftp-data 20/tcp
ftp 21/tcp
fsp 21/udp fspd
ssh 22/tcp # SSH Remote Login Protocol
ssh 22/udp
telnet 23/tcp
smtp 25/tcp mail
.
Jika data lebih panjang dari 1 byte. Bagaimana cara menyusunnya?
int 2 bytes
long 4 bytes
long long 8 bytes
Decimal 11111 = 0x2b67
Big-endian
0x2b 0x67
Little-endian
0x67 0x2b
Everything in Unix is a file.
"a way to speak to other programs using standard Unix file descriptors."
#include <stdio.h>
int main(void)
{
fprintf(stdout, "%s", "write to stdout\n");
fprintf(stderr, "%s", "write to stderr\n");
printf("%d %d %d\n", fileno(stdin), fileno(stdout),
fileno(stderr));
return 0;
}
output:
write to stdout
write to sterr
0 1 2
import sys
if __name__ == '__main__':
sys.stdout.write('write to stdout\n')
sys.stderr.write('write to stderr\n')
print('%d %d %d' % (sys.stdin.fileno(),
sys.stdout.fileno(),
sys.stderr.fileno()))
$ipython
In [1]: import socket
In [2]: socket?
..
Docstring:
This module provides socket operations and some related functions.
On Unix, it supports IP (Internet Protocol) and Unix domain sockets.
On other systems, it only supports IP. Functions specific for a
socket are available as methods of the socket object.
.
Object-based Interface untuk low level socket (POSIX)
In [3]: socket.SOCK
socket.SOCK_DGRAM socket.SOCK_RDM socket.SOCK_STREAM
socket.SOCK_RAW socket.SOCK_SEQPACKET
Datagram socket, connectionless socket.
Stream socket, reliable two-way connected communication stream.
Kegunaan TCP vs. UDP?
Membuat object socket berdasarkan address family (default: AF_INET), tipe stream (SOCK_DGRAM atau default: SOCK_STREAM) dan protocol (0).
Menerima koneksi, mengembalikan socket yang dibuat dan alamat client
bind socket ke alamat local
menutup socket
membuat koneksi dengan alamat remote
mengembalikan alamat remote
mengembalikan alamat local
memulai listening koneksi yang masuk
menerima data
menerima data dan alamat pengirim
mengirim semua data
mengirim data, mungkin tidak semuanya
shut down traffic, satu arah maupun dua arah
Client mengirim pesan msg, server membalas dengan pesan msg yang sama.
1 2 3 4 5 6 7 8 9 10 | import socket
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.bind(('127.0.0.1', 5555))
while True:
msg, address = s.recvfrom(65535) # bytes
print('client %s mengirim %s' % (address, msg))
s.sendto(msg, address)
print('balasan dikirim')
|
1 2 3 4 5 6 7 8 | import socket
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.sendto('Isi pesan', ('127.0.0.1', 5555))
# menerima pesan
msg, address = s.recvfrom(65535) # bukan hanya dari server
print('server %s membalas: %s' % (address, msg))
|
1 2 3 4 5 6 7 8 9 | import socket
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.connect(('127.0.0.1', 5555))
s.send('Isi pesan')
# menerima pesan
msg = s.recv(65535)
print('server membalas: %s' % msg)
|
Mengapa ada send dan sendall?
Apa yang terjadi ketika method send dan recv dipanggil?
bytes_sent = 0
while bytes_sent < len(msg):
msg_remaining = message[bytes_sent:]
bytes_sent += s.send(msg_remaining)
def recv_all(sock, length):
temp = ''
while len(data) < length:
more = sock.recv(length - len(temp))
if not more:
raise EOFError('panjang tidak sesuai')
temp += more
return temp
# utils.py
def recv_until(sock, eof_char='.'):
temp = ''
char = ''
while char != eof_char:
char = sock.recv(1)
if char:
temp += char
else:
break
return temp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | import socket
from utils import recv_until
# passive socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.bind(('127.0.0.1', 5555))
s.listen(1)
while True:
# mengembalikan active/connected socket
sc, sockname = s.accept()
print('koneksi dari %s' % repr(sockname))
msg = recv_until(sc)
sc.sendall(msg)
sc.close()
print('balasan dikirim')
|
1 2 3 4 5 6 7 8 9 10 | import socket
from utils import recv_until
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('127.0.0.1', 5555))
print('socket local %s' % repr(s.getsockname()))
s.sendall('Isi pesan.')
msg = recv_until(s)
print('balasan server: %s' % msg)
s.close()
|
Format pesan
(d/e)(shift)(message).
d: Decrypt (geser kiri) ?
e: Encrypt (geser kanan) ?
shift: jumlah pergeseran (2 digit)
message: plaintext / ciphertext (lowercase)
1 2 3 4 5 6 7 8 | # caesar.py
from string import maketrans
from string import ascii_lowercase as al
def cipher(msg, shift=3):
shifted = al[shift:] + al[:shift]
trans_table = maketrans(al, shifted)
return msg.translate(trans_table)
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | import socket
from utils import recv_until
from caesar import cipher
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.bind(('127.0.0.1', 5555))
s.listen(1)
while True:
sc, sockname = s.accept()
print('koneksi dari %s' % repr(sockname))
msg = recv_until(sc)
try:
nshift = int(msg[1:3])
except ValueError:
nshift = 0
nshift = -nshift if msg[0] == 'd' else nshift
msg = cipher(msg[3:], nshift)
sc.sendall(msg)
sc.close()
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | import socket
from utils import recv_until
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('127.0.0.1', 5555))
s.sendall('e10isi pesan.')
msg = recv_until(s)
print('balasan server: %s' % msg)
s.close()
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('127.0.0.1', 5555))
s.sendall('d10%s' % msg)
msg = recv_until(s)
print('balasan server: %s' % msg)
s.close()
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | import socket
if __name__ == '__main__':
target = raw_input('target: ')
for port in range(20, 1025):
s = socket.socket()
s.settimeout(0.01) # dalam detik
result = s.connect_ex((target, port))
if result == 0:
print('port %d: OPEN' % port)
s.close()
|
Q & A