专栏首页Devops专栏Python 实战TCP的服务端 - 胖子老板就是服务端

Python 实战TCP的服务端 - 胖子老板就是服务端

tcp服务器

胖子老板就是服务端

什么是服务端呢?

你看看你,还问这种问题

肥仔来胖子老板店里买烟,肥仔就是客户端,胖子老板就是服务端。

client (肥仔白) -- "来包利群啦" --> server(胖子老板) client (肥仔白) <-- "给你啦" -- server(胖子老板)

作为客户端是主动访问服务端的,就跟肥仔白主动去胖子老板店铺买烟、买槟榔一样。

作为服务端是监听等待客户端来访问的,就跟胖子老板打着斗地主的游戏,等人来买东西一样。

tcp服务器

在程序中,如果想要完成一个tcp服务器的功能,需要的流程如下:

  1. socket创建一个套接字
  2. bind绑定ip和port
  3. listen使套接字变为可以被动链接
  4. accept等待客户端的链接
  5. recv/send接收发送数据

一个很简单的tcp服务器如下:

[root@server01 tcp]# vim server.py 

#coding=utf-8

from socket import *

# 创建套接字
tcp_server_socket = socket(AF_INET, SOCK_STREAM)

# 绑定服务端提供服务的端口号
local_addr = ('', 7788) #  ip地址和端口号,ip一般不用写,表示本机的任何一个ip

# 绑定
tcp_server_socket.bind(local_addr)

# 使用socket创建的套接字默认的属性是主动的,使用listen将其改为被动,用来监听连接
tcp_server_socket.listen(128)

# 如果有新的客户端来链接服务端,那么就产生一个新的套接字专门为这个客户端服务
# client_socket用来为这个客户端服务
# tcp_server_socket就可以省下来专门等待其他新的客户端连接
client_socket, clientAddr = tcp_server_socket.accept()

# 接收对方发送的数据
recv_data = client_socket.recv(1024) #  1024表示本次接收的最大字节数
print('接收到的数据为:',recv_data.decode('utf-8'))

# 发送一些数据到客户端
client_socket.send("yours lanliqun !".encode('utf-8'))

# 关闭为这个客户端服务的套接字,只要关闭,就意味着不能再为这个客户端服务了。
# 如果客户端还需要服务,则重新建立连接
client_socket.close()

运行如下:

可以看到,服务端的client_socket关闭之后,就无法继续给客户端提供服务了。 那么来升级一下,将服务改成循环。

tcp服务器 - 胖子老板循环版

一次服务不够,需要循环服务

客户端代码如下:

[root@server01 tcp]# vim client.py 

#coding=utf-8

from socket import *

# 创建socket
tcp_client_socket = socket(AF_INET, SOCK_STREAM)

# 服务器的地址
dest_addr = ('127.0.0.1', 7788)  # 注意 是元组,ip是字符串,端口是数字

# 链接服务器,进行tcp三次握手
tcp_client_socket.connect(dest_addr)

while True:
    # 从键盘获取数据
    send_data = input("请输入要发送的数据:")

    # 发送数据到指定的服务端
    tcp_client_socket.send(send_data.encode("utf-8"))

    # 接收对方发送过来的数据,最大接收1024个字节
    recvData = tcp_client_socket.recv(1024)
    print('接收到的数据为:',recvData.decode('utf-8'))

    # 判断输入stop,则退出客户端
    if send_data == "stop":
        break

# 关闭套接字
tcp_client_socket.close()

服务端代码如下:

[root@server01 tcp]# vim server.py 

#coding=utf-8

from socket import *

# 创建套接字
tcp_server_socket = socket(AF_INET, SOCK_STREAM)

# 绑定服务端提供服务的端口号
local_addr = ('', 7788) #  ip地址和端口号,ip一般不用写,表示本机的任何一个ip

# 绑定
tcp_server_socket.bind(local_addr)

# 使用socket创建的套接字默认的属性是主动的,使用listen将其改为被动,用来监听连接
tcp_server_socket.listen(128)

# 如果有新的客户端来链接服务端,那么就产生一个新的套接字专门为这个客户端服务
# client_socket用来为这个客户端服务
# tcp_server_socket就可以省下来专门等待其他新的客户端连接while True:
client_socket, clientAddr = tcp_server_socket.accept()

while True:

    # 接收对方发送的数据
    recv_data = client_socket.recv(1024) #  1024表示本次接收的最大字节数
    print('接收到的数据为:',recv_data.decode('utf-8'))

    # 发送一些数据到客户端
    client_socket.send("yours lanliqun !".encode('utf-8'))

    # 将接收到的数据转换为字符串打印
    recv_result = str(recv_data.decode('utf-8'))
    print("recv_result",recv_result)

    # 当接收到stop,则停止服务
    if recv_result == "stop":
        break

# 关闭为这个客户端服务的套接字,只要关闭,就意味着不能再为这个客户端服务了。
# 如果客户端还需要服务,则重新建立连接
client_socket.close()

## 最后关闭监听的socket
tcp_server_socket.close()

运行如下:

好了,从结果上看,已经完成了循环对话的半双工功能了。 但是上面只能说服务端只派了一个socket做服务,完了就自己也结束了。简单来说,就好像胖子老板的店铺在卖烟,才卖了一包就关门收店铺了。 这明显不合理。

那么下面再来一个循环生成服务client的socket端口,用于持续提供服务。

tcp服务器 - 胖子老板循环版加强版

持续循环,问你怕不怕

其实只要将接收数据处理的部分进行循环即可。

服务端改写代码如下:

[root@server01 tcp]# vim server.py 

#coding=utf-8

from socket import *

# 创建套接字
tcp_server_socket = socket(AF_INET, SOCK_STREAM)

# 绑定服务端提供服务的端口号
local_addr = ('', 7788) #  ip地址和端口号,ip一般不用写,表示本机的任何一个ip

# 绑定
tcp_server_socket.bind(local_addr)

# 使用socket创建的套接字默认的属性是主动的,使用listen将其改为被动,用来监听连接
tcp_server_socket.listen(128)

while True:
    # 如果有新的客户端来链接服务端,那么就产生一个新的套接字专门为这个客户端服务
    # client_socket用来为这个客户端服务
    # tcp_server_socket就可以省下来专门等待其他新的客户端连接while True:
    client_socket, clientAddr = tcp_server_socket.accept()

    while True:

        # 接收对方发送的数据
        recv_data = client_socket.recv(1024) #  1024表示本次接收的最大字节数
        print('接收到的数据为:',recv_data.decode('utf-8'))

        # 发送一些数据到客户端
        client_socket.send("yours lanliqun !".encode('utf-8'))

        # 将接收到的数据转换为字符串打印
        recv_result = str(recv_data.decode('utf-8'))
        print("recv_result",recv_result)

        # 当接收到stop,则停止服务
        if recv_result == "stop":
           break

    # 关闭为这个客户端服务的套接字,只要关闭,就意味着不能再为这个客户端服务了。
    # 如果客户端还需要服务,则重新建立连接
    client_socket.close()

## 最后关闭监听的socket
tcp_server_socket.close()

执行如下:

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • Python 实战TCP的客户端 - 胖子老板,再来一包烟

    client (肥仔白) -- "来包利群啦" --> server(胖子老板) client (肥仔白) <-- "给你啦" -- server(胖子老板)

    Devops海洋的渔夫
  • Python 开发web服务器,多进程优化

    前面写了两个篇章,主要介绍了使用tcp开发web服务器的功能。 Python 开发Web静态服务器 - 返回固定值:胖子老板,来包槟榔 Python 开发w...

    Devops海洋的渔夫
  • Python 开发web服务器,多线程

    其实线程对于性能的提升在python中并不会很高,因为GIL这个全局锁的方式会对多线程进行锁定,导致性能损耗偏大 那么下一步,考虑可以使用协程gevent来优...

    Devops海洋的渔夫
  • tcp服务端socket

    skylark
  • 怒解Workerman之select IO复用(十)

    在第八章和第九章的案例中,哥用socket和fork等基础为为大家表演了如下一波儿:

    老李秀
  • Web静态服务器

    如果在发送文件的时候,有可能一次发送不完整,显示有误,可能是文件太大。我们可以将send方法改成sendall方法,即可解决

    小闫同学啊
  • [PHP] PHP多进程处理tcp连接

    陶士涵
  • 人脸检测(一)——基于单文档的应用台程序

    Opencv自带训练好的人脸模型(人脸的人眼、口等器官类似),此文基于vs2013建立应用台单文档程序,具体建立过程不予详细叙述,主要记录利用的Opencv自带...

    小小詹同学
  • RabbitMQ笔记(三)-基于Docker安装RabbitMQ集群

    .erlang.cookie是erlang实现分布式的必要文件,erlang分布式的每个节点上要保持相同的.erlang.cookie文件,同时保证文件的权限是...

    yingzi_code
  • IPPROTO_IP , IPPROTO_RAW

    对于socket(AF_INET, SOCK_RAW, IPPROTO_IP),其原型为 int socket (int domain, int type, ...

    战神伽罗

扫码关注云+社区

领取腾讯云代金券