Fu
Simple is Beautiful!

network编程:TCP篇

TCP(Transmission Control Protocol,传输控制协议)是一种面向连接的、可靠的、基于字节流的通信协议, 它和 UDP 一样,都处于 TCP/IP 协议的传输层,但是比 UDP 复杂许多。

为了使数据在传输过程中不会发生丢包、变化、错序或出现网络拥堵现象,TCP 自身实现了一系列的功能:

正是由于 TCP 的可靠性,互联网上的许多协议都是基于 TCP 之上的,比如 FTP、Telnet、SMTP、HTTP、POP3 等。

但是由于 TCP 是面向连接的,所以其不能像 UDP 那样实现广播的功能。

socket 简单版

client 端

示例如下:

#!/usr/bin/env python

import socket

ADDR = ('127.0.0.1', 6666)
MESSAGE = 'hello world!'

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(ADDR)

print('Send to server:', MESSAGE)
s.sendall(MESSAGE.encode('utf-8'))
data = s.recv(1024)
print("the server says:", data.decode('utf-8'))

s.close()

server 端

示例如下:

#!/usr/bin/env python

import socket

ADDR = ('127.0.0.1', 6666)

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind(ADDR)
s.listen(1)

while True:
    sock, addr = s.accept()
    print('We have accepted a connection from', addr)
    message = sock.recv(1024)
    print('the client said', message.decode('utf-8'))
    reply = 'you messagge is {} bytes'.format(len(message))
    sock.sendall(reply.encode('utf-8'))
    sock.close()

socket 改进版

由于 TCP 的一系列特性,它与 UDP 代码表面看起来差不多,但背后却大不相同:

TCP 由于以上特点,我们的代码需要改进许多。

client端

#!/usr/bin/env python

import socket

def recv_all(sock, count):
    buf = b''
    while len(buf) < count:
        more = sock.recv(count-len(buf))
        if not more:
            raise EOFError('socket closed {:d} bytes into a {:d}-byte message'
                           .format(len(buf), count))
        buf += more
    return buf

ADDR = ('127.0.0.1', 6666)
MESSAGE = 'hello world!'

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(ADDR)

print('Send to server:', MESSAGE)
message_bytes = MESSAGE.encode('utf-8')
message_length_bytes = '{:04d}'.format(len(message_bytes)).encode('utf-8')
s.sendall(message_length_bytes)
s.sendall(message_bytes)
reply_length_buf = recv_all(s, 4)
reply_length = int(reply_length_buf.decode('utf-8'))
reply = recv_all(s, reply_length)
print("the server says:", reply.decode('utf-8'))

s.close()

server端

#!/usr/bin/env python

import socket

def recv_all(sock, count):
    buf = b''
    while len(buf) < count:
        more = sock.recv(count-len(buf))
        if not more:
            raise EOFError('socket closed {:d} bytes into a {:d}-byte message'
                           .format(len(buf), count))
        buf += more
    return buf

ADDR = ('127.0.0.1', 6666)

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.bind(ADDR)
s.listen(1)

while True:
    sock, addr = s.accept()
    print('We have accepted a connection from', addr)
    message_length_buf = recv_all(sock, 4)
    message_length = int(message_length_buf.decode('utf-8'))
    message = recv_all(sock, message_length)
    print('the client said', message.decode('utf-8'))
    reply_buf = 'you messagge is {} bytes'.format(message_length).encode('utf-8')
    reply_length_buf = '{:04d}'.format(len(reply_buf)).encode('utf-8')
    sock.sendall(reply_length_buf)
    sock.sendall(reply_buf)
    sock.close()
python15network8
2015-03-30 17:26:00