15. Python TCP与UDP编程

建立TCP服务

from socket import *

'''
建立TCP服务端
'''

host = ''
buffersize = 1024
port = 9876
addr = (host, port)

'''
AF_INET:IPV4   AF_INET6 IPV6
SOCK_ATREAM: TCP
'''
# 1. Socket对象
tcpServerSocket = socket(AF_INET, SOCK_STREAM)
# 2. 绑定一个端口号
tcpServerSocket.bind(addr)
# 3. 监听端口号
tcpServerSocket.listen()
print('Server port: 9876')
print('等待客户端连接……')
# 4. 等待客户端Socket连接
tcpClientSocket, addr = tcpServerSocket.accept()
print('客户端已经连接', 'addr', '=', addr)
# 5. 读取从客户端发过来的数据
data = tcpClientSocket.recv(buffersize)
print(data.decode('utf8'))
# 6. 向客户端发送数据
tcpClientSocket.send('你好地球人!Hello'.encode(encoding='utf_8'))
# 7. 关闭客户端的Socket连接
tcpClientSocket.close()
# 8. 关闭服务端的Socket连接
tcpServerSocket.close()

服务端接受数据的缓冲区

from socket import *

'''
服务端接收数据的缓冲区
如果客户端发送给服务端的数据过多,需要分多次读取,每次
最多读取缓冲区尺寸的数据,即 bufferSize
'''

bufferSize = 2
addr = ('', 9876)

tcpServerSocket = socket(AF_INET, SOCK_STREAM)
tcpServerSocket.bind(addr)
tcpServerSocket.listen()
print('等待客户端连接')
tcpClientSocket, addr = tcpServerSocket.accept()
print('客户端已连接')
fullDataBytes = b''

while True:
    data = tcpClientSocket.recv(bufferSize)  # 每次最多读取2字节的数据
    fullDataBytes += data
    if len(data) < bufferSize: break

print(fullDataBytes)
print(fullDataBytes.decode('ISO-8859-1'))
tcpClientSocket.close()
tcpServerSocket.close()

服务端的请求队列

'''
服务端请求队列
'''
from socket import *

bufferSize = 1024
addr = ('', 9876)
tcpServerSocket = socket(AF_INET, SOCK_STREAM)
tcpServerSocket.bind(addr)
tcpServerSocket.listen(2)  # 请求队列,设为2个

print('等待客户端连接')

while True:
    tcpClientSocket, addr = tcpServerSocket.accept()
    print('客户端已连接', addr)
    data = tcpClientSocket.recv(bufferSize)
    if data == b'q': break
    print(data.decode('utf8'))
    tcpClientSocket.send('Hello bor!'.encode(encoding = 'utf-8'))
    tcpClientSocket.close()

tcpServerSocket.close()

时间戳服务器

'''
时间戳服务器
'''

from socket import *
from time import ctime

bufferSize = 1024
addr = ('', 9876)
tcpServerSocket = socket(AF_INET, SOCK_STREAM)
tcpServerSocket.bind(addr)
tcpServerSocket.listen()

while True:
    print('等待连接')
    tcpClientSocket, addr = tcpServerSocket.accept()
    while True:
        data = tcpClientSocket.recv(bufferSize)
        if data == b'q': break
        tcpClientSocket.send(ctime().encode(encoding='GBK') + b'\n ' + data)
    tcpClientSocket.close()
        
tcpServerSocket.close()

用Socket实现简易Http服务器

'''
用Socket实现简易HTTP服务器

HTTP请求头
GET  POST

GET /html/rfc2616 HTTP/1.1
Host: tools.ietf.org
Connection: keep-alive
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9,en;q=0.8

HTTP响应头
HTTP/1.1 200 OK
Accept-Ranges: bytes
Cache-Control: max-age=604800
Connection: Keep-Alive
Content-Encoding: gzip
Content-Location: rfc2616.html
Content-Type: text/html; charset=UTF-8
Date: Sat, 24 Mar 2018 07:52:47 GMT
ETag: "3d2050-83393-567508dabd73a;56823d38ef5d5"
Expires: Sat, 31 Mar 2018 07:52:47 GMT
Keep-Alive: timeout=5, max=100q
Last-Modified: Tue, 13 Mar 2018 19:49:15 GMT
Server: Apache/2.2.22 (Debian)
Strict-Transport-Security: max-age=3600
TCN: choice
Transfer-Encoding: chunked
Vary: negotiate,Accept-Encoding
X-Clacks-Overhead: GNU Terry Pratchett
X-Content-Type-Options: nosniff
X-Frame-Options: SAMEORIGIN
X-Xss-Protection: 1; mode=block
'''
from socket import *
import os

def reponseHanders(length):
    '''
    从文件中读取要返回的Http响应头文本,并将设置返回数据长度为length
    '''
    f = open('./reponse_headers.txt', 'r')
    headersText = f.read()
    headersText = headersText % length
    return headersText

def filePath(get):
    '''
    根据http请求头的路径得到服务端的静态文件
    '''
    if get == '':
        return './static' + os.sep + 'index.html'
    else:
        paths = get.split('/')
        s = './static'
        for path in paths:
            if path.strip() != '':
                s += (os.sep + path)
        return s

addr = ('', 9876)
buffersize = 1024
tcpServerSocket = socket(AF_INET, SOCK_STREAM)
tcpServerSocket.bind(addr)
tcpServerSocket.listen()

while True:
    print('等待客户端连接...')
    tcpClientSocket, addr = tcpServerSocket.accept()
    print('客户端已经连接, addr = ', addr)
    data = tcpClientSocket.recv(buffersize)
    data = data.decode('utf-8')
    try:
        # 获取请求头的第一行
        firstline = data.split('\n')[0]
        print(firstline)
        # 获取请求路径, exp: GET /html/rfc2616 HTTP/1.1
        path = firstline.split(' ')[1]
        path = filePath(path)
        if os.path.exists(path):
            file = open(path, 'rb')
            content = file.read()
            file.close()
        else:
            content = '

File not found!

'.encode(encoding='utf_8') rh = reponseHanders(len(content)) + '\r\n' tcpClientSocket.send(rh.encode(encoding='utf-8') + content) except Exception as e: print(e) tcpClientSocket.close() tcpServerSocket.close()

客户端Socket

'''
客户端socket
'''
from socket import *

buffersize = 1024
addr = ('localhost', 9876)

tcpClientSocket = socket(AF_INET, SOCK_STREAM)
tcpClientSocket.connect(addr)

while True:
    data = input('>>> ')
    # 输入空字符串退出
    if not data: break
    data = data.encode(encoding='utf-8')
    tcpClientSocket.send(data)
    data = tcpClientSocket.recv(buffersize)
    print(data.decode('utf-8'))

UDP时间戳服务器和客户端

'''
UDP时间戳服务器
TCP: 面向连接的协议
UDP: 无连接的协议
'''
from socket import *
from time import ctime

addr = ('', 9876)
buffersize = 1024

udpServerSocket = socket(AF_INET, SOCK_DGRAM)
udpServerSocket.bind(addr)

while True:
    print('正在等待消息。。。')
    data, addr = udpServerSocket.recvfrom(buffersize)
    udpServerSocket.sendto(ctime().encode(encoding='utf-8') + b' ' + data, addr)

udpServerSocket.close()
'''
UDP时间戳客户端
'''
from socket import *

buffersize = 1024
addr = ('localhost', 9876)
udpClientSocket = socket(AF_INET, SOCK_DGRAM)

while True:
    data = input('>>> ')
    if not data: break
    udpClientSocket.sendto(data.encode(encoding='utf-8'), addr)
    data, addr = udpClientSocket.recvfrom(buffersize)
    if not data: break
    print(data.decode('utf-8'))
udpClientSocket.close()

sockerserver类

'''
socketServer TCP时间戳服务器
'''
from socketserver import (TCPServer as TCP, StreamRequestHandler as SRH)
from time import ctime

addr = ('', 9876)

class MyRequestHander(SRH):
    def handle(self):
        print('客户端已连接, 地址:', self.client_address)
        self.wfile.write(ctime().encode(encoding='utf-8') + b' ' + self.rfile.readline())

tcpServer = TCP(addr, MyRequestHander)
tcpServer.serve_forever()

练习

'''
使用UDP Socket编写一个可以计算Python表达式的服务端应用,
然后再编写一个用于测试这个服务端应用的客户端程序。
在客户端程序中输入Python表达式,然后将表达式字符串传到服务端,
服务端执行后,再将结果返回给客户端程序。
'''
'''
服务端
'''
from socket import *
 
addr = ('', 9876)
buffersize = 1024
udpServerSocket = socket(AF_INET, SOCK_DGRAM)
udpServerSocket.bind(addr)

while True:
    print('正在等待消息。。。')
    data, addr = udpServerSocket.recvfrom(buffersize)
    data = data.decode(encoding = 'utf-8')
    print('已接收到表达式:{}, 地址:{}'.format(data, addr))
    try:
        data = eval(data)
    except Exception as e:
        print(e)
        data = '无效的表达式:{}'.format(data)
    data = str(data)
    udpServerSocket.sendto(data.encode(encoding='utf-8'), addr)
udpServerSocket.close()
'''
使用UDP Socket编写一个可以计算Python表达式的服务端应用,
然后再编写一个用于测试这个服务端应用的客户端程序。
在客户端程序中输入Python表达式,然后将表达式字符串传到服务端,
服务端执行后,再将结果返回给客户端程序。
'''
'''
客户端
'''
from socket import *
 
addr = ('localhost', 9876)
buffersize = 1024
udpClientSocket = socket(AF_INET, SOCK_DGRAM)

while True:
    expression = input('>>> ')
    if not expression: break
    udpClientSocket.sendto(expression.encode(encoding='utf_8'), addr)
    data, addr = udpClientSocket.recvfrom(buffersize)
    if not data: break
    print('计算结果:', data.decode('utf-8'))
udpClientSocket.close() 

你可能感兴趣的:(15. Python TCP与UDP编程)