- socket库实现tcp的服务器和客户端
- socketserver库实现tcp的服务器和客户端
- twisted框架实现tcp服务器和客户端
- 课后习题
注意: server和client的端口PORT要相同
踩坑: 发送数据的函数,如 socket.send(),接受bytes类型,不能直接传入字符串会报类型错TypeError: a bytes-like object is required, not 'str'
,需要对字符串执行encode()函数把返回的bytes类型对象传进
socket库:
tcp server:
from socket import *
from time import ctime
HOST = ""
PORT = 7000
ADDR = (HOST, PORT)
BUFSIZ = 1024
tcpSerSock = socket(AF_INET, SOCK_STREAM)
tcpSerSock.bind(ADDR)
tcpSerSock.listen(5)
while True:
print("Waiting for connect...")
tcpCliSock, addr = tcpSerSock.accept()
print('...connected from:' + str(addr))
while True:
data = tcpCliSock.recv(BUFSIZ).decode()
if not data:
break
tcpCliSock.send(('[%s] %s' %(ctime(), data)).encode())
tcpCliSock.close()
tcpCliSock.close()
tcp client:
from socket import *
DEFAULT_HOST = '127.0.0.1'
DEFAULT_PORT = 8000
BUFSIZ = 1024
ADDR = (DEFAULT_HOST, DEFAULT_PORT)
tcpCliSocket = socket(AF_INET, SOCK_STREAM)
tcpCliSocket.connect(ADDR)
while True:
data = input('> ') # 输入
if not data:
break
tcpCliSocket.send(data.encode())
data = tcpCliSocket.recv(BUFSIZ)
if not data:
break
print(data.decode())
tcpCliSocket.close()
socketserver库:
tcp server:
from socketserver import (TCPServer as tcp, StreamRequestHandler as srh)
from time import ctime
HOST = ''
PORT = 9000
ADDR = (HOST, PORT)
class MyRequestHandler(srh):
def handle(self):
print('...connect from:' + str(self.client_address))
self.wfile.write(('[%s] %s' % (ctime(), self.rfile.readline().decode())).encode())
tcpserv = tcp(ADDR, MyRequestHandler)
print('waiting for connection')
tcpserv.serve_forever()
tcp client:
from socket import *
HOST = '127.0.0.1'
PORT = 9000
BUFSIZ = 1024
ADDR = (HOST, PORT)
while True:
tcpsock = socket(AF_INET, SOCK_STREAM)
tcpsock.connect(ADDR)
data = input('> ')
if not data:
break
tcpsock.send('{}\r\n'.format(data).encode())
data = tcpsock.recv(BUFSIZ)
if not data:
break
print(data.decode().strip())
tcpsock.close()
twisted:
tcp server
from twisted.internet import protocol, reactor
from time import ctime
PORT = 9000
class TSServerProtocol(protocol.Protocol):
def connectionMade(self):
clnt = self.clnt = self.transport.getPeer().host
print('...connected from:' + str(clnt))
def dataReceived(self, data):
self.transport.write(('[%s] %s' % (ctime(), data.decode())).encode())
factory = protocol.Factory()
factory.protocol = TSServerProtocol
print('waiting for connecting...')
reactor.listenTCP(PORT, factory)
reactor.run()
tcp client
from twisted.internet import protocol, reactor
HOST= '127.0.0.1'
PORT = 9000
class TSClntProtocol(protocol.Protocol):
def sendData(self):
data = input('> ')
if not data:
self.transport.loseConnection()
else:
print('...sendding %s' % data)
self.transport.write(data.encode())
def connectionMade(self):
self.sendData()
def dataReceived(self, data):
print(data.decode())
self.sendData()
class TSClntFactory(protocol.ClientFactory):
protocol = TSClntProtocol
clientConnectionLost = clientConnectionFailed = lambda self, connector, reason: reactor.stop()
reactor.connectTCP(HOST, PORT, TSClntFactory())
reactor.run()
课后习题答案:
2-4:
#tcpClient
from socket import *
DEFAULT_HOST = '127.0.0.1'
DEFAULT_PORT = 8000
BUFSIZ = 1024
def getHost():
return input('input your host:') or DEFAULT_HOST
def getPort():
return input('input your port:') or DEFAULT_PORT
ADDR = (getHost(), int(getPort()))
tcpCliSocket = socket(AF_INET, SOCK_STREAM)
tcpCliSocket.connect(ADDR)
while True:
data = input('> ') # 输入
if not data:
break
tcpCliSocket.send(data.encode())
data = tcpCliSocket.recv(BUFSIZ)
if not data:
break
print(data.decode())
tcpCliSocket.close()
2-5:
#server
from socket import *
from time import ctime
import os
import re
HOST = ""
PORT = 7000
ADDR = (HOST, PORT)
BUFSIZ = 1024
tcpSerSock = socket(AF_INET, SOCK_STREAM)
tcpSerSock.bind(ADDR)
tcpSerSock.listen(5)
dic = {'data': '%s' % ctime(), 'os': os.name, 'ls': str(os.listdir(os.curdir))}
while True:
print("Waiting for connect...")
tcpCliSock, addr = tcpSerSock.accept()
print('...connected from:' + str(addr))
while True:
data = tcpCliSock.recv(BUFSIZ).decode()
dirRe = re.match(r'ls dir\((.+)\)', data)
if not data:
break
elif dic.get(data):
tcpCliSock.send(dic[data].encode())
elif dirRe:
print(os.listdir(dirRe.group(1)))
tcpCliSock.send(str(os.listdir(dirRe.group(1))).encode())
else:
tcpCliSock.send(str(data).encode())
tcpCliSock.close()
tcpCliSock.close()
2-10:
多用户要用到select来监听多个client, 全双工在client端要用到双线程, 不然input函数会阻塞, 一个线程负责input, 另一个线程负责接受server发送过来的消息
这是一个select模块的讲解
#server
from socket import *
import select
import re
HOST = ''
PORT = 8000
BUFSIZ = 1024
ADDR = (HOST, PORT)
server = socket(AF_INET, SOCK_STREAM)
server.bind(ADDR)
server.listen(5)
inputs = [server]
clientDic = {}
default_name = 'someone'
default_room = 0
while True:
r_list, w_list, e_list = select.select(inputs, [], inputs, 1)
for i in r_list:
if i is server:
client, addr = server.accept()
print('connect from: ' + str(addr))
inputs.append(client)
clientDic[client] = [addr, default_name, default_room]
# client.send('welcome!!'.encode())
else:
try:
data = i.recv(BUFSIZ).decode()
print(data)
matchname = re.match(r'(.+)\sjoin the server', data)
matchroom = re.match(r'Join the room(\d)', data)
# 找到名字
if matchname:
clientDic[i][1] = matchname.group(1)
i.send('welcome!! {}'.format(clientDic[i][1]).encode())
for c, v in clientDic.items():
if c is i:
continue
elif v[1] == default_name or v[2] == default_room:
continue
else:
c.send(data.encode())
# 找到房间
elif matchroom:
clientDic[i][2] = matchroom.group(1)
i.send('you join room {}'.format(clientDic[i][2]).encode())
for c, v in clientDic.items():
if c is i:
continue
elif v[1] != default_room and v[2] == clientDic[i][2]:
c.send((clientDic[i][1] + ' ' + data).encode())
else:
continue
# 发送消息
else:
for c, v in clientDic.items():
if v[1] != default_name and v[2] == clientDic[i][2]:
c.send((clientDic[i][1] + ': ' + data).encode())
flag = True
except ConnectionResetError:
flag = False
# 断开连接
if not flag:
left = clientDic[i][1] + ' left'
print(left)
del clientDic[i]
for c, v in clientDic.items():
c.send(left.encode())
inputs.remove(i)
#client
from socket import *
import threading
HOST = 'localhost'
PORT = 8000
BUFSIZ = 1024
ADDR = (HOST, PORT)
tcpCliSock = socket(AF_INET, SOCK_STREAM)
tcpCliSock.connect(ADDR)
username = input("Please set your username:")
tcpCliSock.send("{} join the server".format(username).encode())
data = tcpCliSock.recv(BUFSIZ).decode()
print(data)
room = input("Input room number(Input a number 1-9):")
tcpCliSock.send("Join the room{}".format(room).encode())
data = tcpCliSock.recv(BUFSIZ).decode()
print(data)
def send():
while True:
data = input(' > ')
if not data:
continue
else:
tcpCliSock.send(data.encode())
def receive():
while True:
data = tcpCliSock.recv(BUFSIZ).decode()
print(data)
print(' > ')
t1 = threading.Thread(target=send)
t2 = threading.Thread(target=receive)
t1.start()
t2.start()
t1.join()
t2.join()
tcpCliSock.close()
未完...