Python实现SocketServer(一)

说明

TCP 服务器是web后端开发必须学习的一环,此文章记录了我个人在学习python web开发过程中开发SocketServer的流程

Socket通信流程

TODO
网上找的图

逐步实现SocketServer

实现单次Soket Server与Client逻辑

依照以上述逻辑,使用python 标准库socket 模块实现单次接收/发送的Server/Client.

注:开始未将代码写成类是应为个人觉得OOP主要用来复用代码、解耦、抽象化复杂对象,对于第一步来说,使用类反而会让整个TCPServer创建流程不够直观。因此我会在后面需要的步骤将其重构为类

socket构造参数
参数含义
family默认为AF_INET协议簇,指定socket使用的协议,默认使用IPv4协议簇
type默认值未SOCKET_STREAM指定套接字类型,默认为流式套接字
proto默认值为0指定套接字使用协议簇中的哪个协议,默认为TCP协议
fileno默认值为None指定socket打开的文件描述符
socket常用方法
方法参数含义
bind()address绑定socket到特点的ip和port上,形式为(‘127.0.0.1’, 80)
listen()开始监听请求
accept()接收请求,在未收到请求时阻塞
send()bytes、flags(可选)发送二进制数据,flags是一系列标志,可以控制发送的行为
rcev()buffersize, flags(可选)指定接收缓冲区的大小,flags可控制接收行为

其他的方法不列举了,以后用到在写.

Code
  • Client Code
#!/usr/bin/env python3
# encoding: utf-8

from socket import socket, AF_INET, SOCK_STREAM


def client(server_addr, msg):
    """
    This function is a simple client to connect to TCPserver.

    Args:
        server_addr: String of Server IP address.
        msg: The message that you want to send to server.It't type can
            be str or bytes
    """
    with socket(AF_INET, SOCK_STREAM) as sock  # TCP/IPv4 Socket
        sock.connect(server_addr)
        if not isinstance(msg, bytes):
            msg = bytes(msg, 'utf-8')
        sock.send(msg)
        data = sock.recv(4096)
        print(data.decode('utf-8'))


if __name__ == '__main__':
    client(('127.0.0.1', 8080), "I'm client.")
  • ServerCode
#!/usr/bin/env python3
# encoding: utf-8
from socket import socket as Socket, AF_INET, SOCK_STREAM
from sys import exit, stderr
import logging


logging.basicConfig(
    level=logging.INFO,
    stream=stderr,
    format="[%(levelname)s] %(asctime)s %(message)s"
)
log = logging.getLogger('SocketServer')


def check_addr(address):
    """
    Check server address format
    Not complete. TODO
    """
    # check address
    if len(address) < 2:
        exit("You miss ip address or port.")
    ip_addr, port = address

    # Check port format
    if isinstance(port, str):
        try:
            port = int(port)
        except ValueError:
            exit("Error Port Number: %s" % port)
    return (ip_addr, port)


def recv_msg(socket):
    """Receive message from client"""
    data = socket.recv(4096)
    if isinstance(data, bytes):
        data = data.decode('utf-8')
    log.info("The receive data from client is: %s", data)


def send_msg(socket, msg):
    """Send message to client"""
    socket.send(bytes(msg, 'uft-8'))
    log.info("Send '%s' to client", msg)


def server(address=None, *, ip_addr=None, port=None):
    """
    This is a simple TcpServer.It can receive data once from client.

    Args:
        ip_addr: String of ip address which server bind.
        port: The port number which server bind. Type can be int or str.
        address: Tuple like ('127.0.0.1', 80). Contain ip_addr and port. If
            you use ip_addr or port with address param, it will override these.
    """
    if not address:
        address = (ip_addr, port)
    address = check_addr(address)

        with Socket(AF_INET, SOCKET_STREAM) as socket:
            socket.bind(address)
            s, _ = socket.accept()
            recv_msg(s)
            send_msg(s, 'Hello')

    log.info("The Tcp Server close.")


if __name__ == "__main__":
    server(('127.0.0.1', 8080))

接下来的计划

下面这些问题将在下一篇文章中解决
- 实现服务端接收多个client访问
- 当server处理程序消耗时间长时提高server处理效率

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值