Python 网络编程(TCP、UDP)
2018-01-08 本文已影响237人
_YZG_
TCP
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import socket
# 创建一个socket:AF_INET指IPv4,IPv6为AF_INET6
# SOCK_STREAM指定使用面向流的TCP协议
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 建立连接: 端口号80是Web服务的标准端口
# 端口号小于1024的是Internet标准服务的端口,端口号大于1024的,可以任意使用。
s.connect(('www.sina.com.cn', 80))
# 发送数据:
s.send(b'GET / HTTP/1.1\r\nHost: www.sina.com.cn\r\nConnection: close\r\n\r\n')
# 接收数据:
buffer = []
while True:
# 每次最多接收1k字节:
d = s.recv(1024)
if d:
buffer.append(d)
else:
break
data = b''.join(buffer)
# 关闭连接:
s.close()
header, html = data.split(b'\r\n\r\n', 1)
print(header.decode('utf-8'))
# 把接收的数据写入文件:
with open('sina.html', 'wb') as f:
f.write(html)
客户端、服务端简单例子
server
一个Socket依赖4项:服务器地址、服务器端口、客户端地址、客户端端口来唯一确定一个Socket。
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import socket, threading, time
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 监听端口:
s.bind(('127.0.0.1', 9999))
# 开始监听端口,传入的参数指定等待连接的最大数量
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()
# 创建新线程来处理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_']:
# 发送数据:
s.send(data)
print(s.recv(1024).decode('utf-8'))
s.send(b'exit')
s.close()
server-client
UDP
UDP的使用与TCP类似,但是不需要建立连接。此外,服务器绑定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...')
# 不需要调用listen()方法,而是直接接收来自任何客户端的数据
while True:
# 接收数据:
# recvfrom()方法返回数据和客户端的地址与端口,这样,服务器收到数据后,直接调用sendto()就可以把数据用UDP发给客户端
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)
# 不需要调用connect(),直接通过sendto()给服务器发数据
for data in [b'yzg', b'YZG', b'_YZG_']:
# 发送数据:
s.sendto(data, ('127.0.0.1', 9999))
# 接收数据:
# 从服务器接收数据仍然调用recv()方法
print(s.recv(1024).decode('utf-8'))
s.close()