TCP
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import socket
# 創(chuàng)建一個socket:AF_INET指IPv4救欧,IPv6為AF_INET6
# SOCK_STREAM指定使用面向流的TCP協(xié)議
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 建立連接: 端口號80是Web服務(wù)的標準端口
# 端口號小于1024的是Internet標準服務(wù)的端口锣光,端口號大于1024的,可以任意使用蹬刷。
s.connect(('www.sina.com.cn', 80))
# 發(fā)送數(shù)據(jù):
s.send(b'GET / HTTP/1.1\r\nHost: www.sina.com.cn\r\nConnection: close\r\n\r\n')
# 接收數(shù)據(jù):
buffer = []
while True:
# 每次最多接收1k字節(jié):
d = s.recv(1024)
if d:
buffer.append(d)
else:
break
data = b''.join(buffer)
# 關(guān)閉連接:
s.close()
header, html = data.split(b'\r\n\r\n', 1)
print(header.decode('utf-8'))
# 把接收的數(shù)據(jù)寫入文件:
with open('sina.html', 'wb') as f:
f.write(html)
客戶端、服務(wù)端簡單例子
server
一個Socket依賴4項:服務(wù)器地址办成、服務(wù)器端口、客戶端地址某弦、客戶端端口來唯一確定一個Socket而克。
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import socket, threading, time
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 監(jiān)聽端口:
s.bind(('127.0.0.1', 9999))
# 開始監(jiān)聽端口,傳入的參數(shù)指定等待連接的最大數(shù)量
s.listen(5)
print('Waiting for connection...')
def tcplink(sock, addr):
print('Accept new connection from %s:%s...' % addr)
sock.send(b'Welcome!')
while True:
data = sock.recv(1024)
time.sleep(1)
if not data or data.decode('utf-8') == 'exit':
break
sock.send(('Hello, %s!' % data.decode('utf-8')).encode('utf-8'))
sock.close()
print('Connection from %s:%s closed.' % addr)
while True:
# 接受一個新連接:
sock, addr = s.accept()
# 創(chuàng)建新線程來處理TCP連接:
t = threading.Thread(target=tcplink, args=(sock, addr))
t.start()
client
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 建立連接:
s.connect(('127.0.0.1', 9999))
# 接收歡迎消息:
print(s.recv(1024).decode('utf-8'))
for data in [b'yzg', b'YZG', b'_YZG_']:
# 發(fā)送數(shù)據(jù):
s.send(data)
print(s.recv(1024).decode('utf-8'))
s.send(b'exit')
s.close()
server-client
UDP
UDP的使用與TCP類似腾降,但是不需要建立連接碎绎。此外,服務(wù)器綁定UDP端口和TCP端口互不沖突筋帖,也就是說,UDP的9999端口與TCP的9999端口可以各自綁定蚁滋。
server
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import socket
# SOCK_DGRAM指定了這個Socket的類型是UDP
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
# 綁定端口:
s.bind(('127.0.0.1', 9999))
print('Bind UDP on 9999...')
# 不需要調(diào)用listen()方法赘淮,而是直接接收來自任何客戶端的數(shù)據(jù)
while True:
# 接收數(shù)據(jù):
# recvfrom()方法返回數(shù)據(jù)和客戶端的地址與端口,這樣梢卸,服務(wù)器收到數(shù)據(jù)后,直接調(diào)用sendto()就可以把數(shù)據(jù)用UDP發(fā)給客戶端
data, addr = s.recvfrom(1024)
print('Received from %s:%s.' % addr)
reply = 'Hello, %s!' % data.decode('utf-8')
s.sendto(reply.encode('utf-8'), addr)
client
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
# 不需要調(diào)用connect(),直接通過sendto()給服務(wù)器發(fā)數(shù)據(jù)
for data in [b'yzg', b'YZG', b'_YZG_']:
# 發(fā)送數(shù)據(jù):
s.sendto(data, ('127.0.0.1', 9999))
# 接收數(shù)據(jù):
# 從服務(wù)器接收數(shù)據(jù)仍然調(diào)用recv()方法
print(s.recv(1024).decode('utf-8'))
s.close()