# 这里边是一个定义了服务端的一系列函数,是Python网络编程这本书第七章的第一个例子。
# 这是供后边函数进行调用了,然后我们来进行研究网络的单线程编程,多线程编程、异步网络编程等。

# 导入网络编程socket、时间time、cmd参数获取模块
import argparse, socket, time

# 定义一个字典用来存放发送给客户端的消息。
aphorisms = {b'Beautiful is better than?': b'Ugly.',
b'Explicit is better than?': b'Implicit.',
b'Simple is better than?': b'Complex.'}

# 获取答案, 如果客户端发送了问题,就从上边的字典里边获取,如果没有的话就返回我不知道的错误。
def get_answer(aphorism):
"""Return the string response to a particular Zen-of-Python aphorism."""
time.sleep(0.0) # increase to simulate an expensive operation
return aphorisms.get(aphorism, b'Error: unknown aphorism.')

# 定义一个函数用来获取终端需要传入的参数。 host:主机IP或者名称 -p:端口,默认为1060
# 返回值是一个元祖,包含IP端口。
def parse_command_line(description):
"""Parse command line and return a socket address."""
parser = argparse.ArgumentParser(description=description)
parser.add_argument('host', help='IP or hostname')
parser.add_argument('-p', metavar='port', type=int, default=1060,
help='TCP port (default 1060)')
args = parser.parse_args()
address = (args.host, args.p)
return address

# 创造一个socket套接字,这里的入参是上边那个函数的出参。
def create_srv_socket(address):
"""Build and return a listening server socket."""
# 创造一个套接字。
listener = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 设置。
listener.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
# 服务端绑定IP和端口。
listener.bind(address)
# 设置服务端能够监听的数量,这里设置的是最大能够同时监听64个。
listener.listen(64)
# 打印出绑定的IP端口,服务端绑定的。
print('Listening at {}'.format(address))
# 返回这个套接字。
return listener

# 一直持续不断的进行监听, 观察有没有客户端和服务端进行连接。
# 这里的入参是上边函数的出参
def accept_connections_forever(listener):
"""Forever answer incoming connections on a listening socket."""
# 死循环
while True:
# 服务端一直在监听端口,看有没有客户端进行连接。
# 这个是阻塞的,如果有的话那么才会进行下边的操作。
sock, address = listener.accept()
# 打印出客户端IP端口
print('Accepted connection from {}'.format(address))
handle_conversation(sock, address)

# 处理连接对话函数。
def handle_conversation(sock, address):
"""Converse with a client over `sock` until they are done talking."""
try:
while True:
# 这里一直处理客户端的请求。
handle_request(sock)
# 接收异常,代表着客户端断开了连接。
except EOFError:
print('Client socket to {} has closed'.format(address))
# 如果有其他错误,我们也需要进行接收下来。
except Exception as e:
print('Client {} error: {}'.format(address, e))
# 最后关闭服务端的套接字。
finally:
sock.close()

# 处理请求函数。
def handle_request(sock):
"""Receive a single client request on `sock` and send the answer."""
# 这里我们调用函数进行接收客户端发送过来的消息。
aphorism = recv_until(sock, b'?')
# 然后调用获取答案函数,将我们的答案回复给客户端。
answer = get_answer(aphorism)
# 服务端进行发送消息
sock.sendall(answer)

# 服务端和客户端进行连接后,一直进行接收客户端发送过来的消息,直到客户端发送了suffix
# 这里我们的入参为?,如果客户端发送了suffix就代表着客户端发送完了消息。就需要进行关闭了。
def recv_until(sock, suffix):
"""Receive bytes over socket `sock` until we receive the `suffix`."""
# 接收数据,
message = sock.recv(4096)
# 如果数据为空。就抛出一个连接关闭的错误。
if not message:
raise EOFError('socket closed')
# 判断接收的消息最后是否是suffix,如果是地话,那我们就直接反悔了。
# 如果不是,就代表着客户端还有数据进行发送,服务端就需要继续进行接收。
while not message.endswith(suffix):
# 能够进来while循环,就代表着客户端还有数据进行发送,
# 那么我们需要继续进行接收
data = sock.recv(4096)
# 如果客户端的数据为空。
# 再次抛出一个异常。
if not data:
raise IOError('received {!r} then socket closed'.format(message))
message += data
# 返回接收的数据。
return message

03Python网络编程系列之服务端的更多相关文章

  1. 03Python网络编程之单线程服务端

    # 对于单线程的服务端,我们借助于zen_utils(我们自己编写好的一些函数)是很容易就实现的.# 导入这个模块import zen_utilsif __name__ == '__main__': ...

  2. TCP/IP网络编程之多进程服务端(二)

    信号处理 本章接上一章TCP/IP网络编程之多进程服务端(一),在上一章中,我们介绍了进程的创建和销毁,以及如何销毁僵尸进程.前面我们讲过,waitpid是非阻塞等待子进程销毁的函数,但有一个不好的缺 ...

  3. TCP/IP网络编程之多线程服务端的实现(二)

    线程存在的问题和临界区 上一章TCP/IP网络编程之多线程服务端的实现(一)的thread4.c中,我们发现多线程对同一变量进行加减,最后的结果居然不是我们预料之内的.其实,如果多执行几次程序,会发现 ...

  4. 基于TCP的socket套接字的网络编程(客户端/服务端模式)

    于数据完整性要求较高的场合,就应采用TCP协议. IP网络层提供IP寻址和路由.因为在网络上数据可以经由多条线路到达目的地,网络层负责找出最佳的传输线路. IP地址与数据包: IP层就是把数据分组从一 ...

  5. TCP/IP网络编程之多进程服务端(一)

    进程概念及应用 我们知道,监听套接字会有一个等待队列,里面存放着不同客户端的连接请求,如果有一百个客户端,每个客户端的请求处理是0.5s,第一个客户端当然不会不满,但第一百个客户端就会有相当大的意见了 ...

  6. 1、简述在java网络编程中,服务端程序与客户端程序的具体开发步骤?

    网络编程分为UDP通信和TCP通信 UDP协议: 发送端:1.创建DatagramSocket对象.2.创建DatagramPacket对象,并封装数据.3.发送数据.4.释放 资源. 接收端:1.创 ...

  7. python网络编程:socket、服务端、客户端

    本文内容: socket介绍 TCP: 服务端 客户端 UDP: 服务端 客户端 首发时间:2018-02-08 01:14 修改: 2018-03-20 :重置了布局,增加了UDP 什么是socke ...

  8. TCP/IP网络编程之多线程服务端的实现(一)

    为什么引入线程 为了实现服务端并发处理客户端请求,我们介绍了多进程模型.select和epoll,这三种办法各有优缺点.创建(复制)进程的工作本身会给操作系统带来相当沉重的负担.而且,每个进程有独立的 ...

  9. Java网络编程(TCP协议-服务端和客户端交互)

    客户端: package WebProgramingDemo; import java.io.IOException; import java.io.InputStream; import java. ...

随机推荐

  1. python进程间共享数值、字典、列表变量

    ##python进程间共享数值.字典.列表变量 关注公众号"轻松学编程"了解更多. import multiprocessing def worker(num, mgr_dict, ...

  2. P6064 [USACO05JAN]Naptime G

    最近做了多少道 usaco 了,连 FJ 都认识我了呀 题意描述 传送门 给你 \(N\) 段时间其中 \(B\) 段时间你要用来睡眠,再给你每个时间睡眠可获得的效用值 \(U_i\). 可惜的是你每 ...

  3. 由python工作区导致的python代码能运行,但是PyCharm画红线的问题

    原文:https://www.zhihu.com/question/63028700 PyCharm在遇到模块找不到时,会使用红色波浪线提醒开发者. Python有一个工作区的概念,在默认情况下,当你 ...

  4. Centos7系统kvm虚机忘记密码进不去, 通过宿主机修改/etc/shadow文件改密码,重启后系统起不来故障排错

    问题描述 某天, 因为其他项目组交接问题, kvm里面的堡垒机系统用户root密码登录不上,然后他通过宿主机修改/etc/shadow文件修改密码,但是修改完后重启系统后发现kvm宿主机连接不上虚机了 ...

  5. 【SpringCloud】07.应用间的通信

    应用间通信 HTTP vs RPC Spring Cloud (HTTP) Dubbo (RPC) 1.SpringCloud中服务间两种restful调用方式 RestTemplate Feign ...

  6. 超值干货 | 建议收藏:精美详尽的 HTTPS 原理图注意查收!

    作为一个有追求的程序员,了解行业发展趋势和扩充自己的计算机知识储备都是很有必要的,特别是一些计算机基础方面的内容,就比如本篇文章要讲的计算机网络方面的知识.本文将为大家详细梳理一下 HTTPS 的实现 ...

  7. Oracle guide_Spring2.5_CN_reference_pdf

    http://www.oracle.com/pls/db112/homepage spring_CN.rar (3.1 MB) 下载次数: 2

  8. TIP/Collision-Free Video Synopsis Incorporating Object Speed and Size Changes Code

    代码地址  https://github.com/scutlzk/Collision-Free-Video-Synopsis-Incorporating-Object-Speed-and-Size-C ...

  9. git命令学习之clone指定分支代码

    今天要拉取一个项目,但是是一个指定分支,本来我以为直接git clone就行,但是发现好像不能,报错: Cloning into 'lecture'...fatal: unable to update ...

  10. mysql之事物

    1.事物,在事物中的sql语句,要么全部执行成功,要么全部执行失败,不会出现一条sql执行成功了,一条sql执行失败的问题. 2.开启事物:就是关闭mysql自己的自动提交事物的方式 3.commit ...