读《Python核心编程》第二章

  1. socket库实现tcp的服务器和客户端
  2. socketserver库实现tcp的服务器和客户端
  3. twisted框架实现tcp服务器和客户端
  4. 课后习题

注意: 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()

未完...

你可能感兴趣的:(读《Python核心编程》第二章)