# 这个程序我们是测试客户端和服务端在进行通信的过程中,可能会产生死锁的情况。

# 这是因为缓冲区,和TCP协议的可靠性连接导致的。

# 在程序中我们可以看到,客户端先向服务端发送数据,然后服务端就收之后再发送给客户端。

# 注意这里我们可以看到,程序设置的是不能缓冲区满就立即发送出去。

# 那么我们可以考虑一下,如果客户端需要发送的字节数比较小,那么是能够正常的通信的,

# 因为小于缓冲区的大小,不会把缓冲区填满。

# 再来考虑客户端发送数据很大的情况比如说1个G。

# 从流程上边来看,客户端的一条信息就会发送出去,而不是等着缓冲区满。

# 服务端那边也是这样的,接收到数据之后直接就发送,此时就产生问题了,因为要发送的数据是很大的,

# 客户端的数据没有发送完成,就无法调用recv接收服务端穿过来的数据,那从服务端看,服务端发送的数据

# 客户端没有接收,TCP 就判断网络不好了,就会不让服务端发送字节。同时服务端也不接受字节,就会导致

# 客户端也发送不出去。这样就导致死锁了。

# 导入模块
import argparse,socket,sys
def server(host,port,bytecount):
# 创建一个服务端的套接字。
sock = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
# 设置套接字
sock.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
# 套接字绑定IP,端口
sock.bind((host,port))
# 设置监听的数量为1
sock.listen(1)
# 打印出服务端的IP,端口
print("Listening at ",sock.getsockname())
while True:
# 服务端的套接字连接上客户端的套接字
sc,sockname = sock.accept()
print("Processing up to 1024 bytes at a time from",sockname)
# 定义一个变量,用来计算一共接收了多少字节。
n = 0
# 死循环,一直接收客户端发过来的字母
while True:
# 每次接收从最大客户端传过来的1024个字节,然后赋给data变量
data = sc.recv(1024)
# 约定一个结束符
if data == b'efo' or data == b'':break
# 将接收的二进制字节进行解码,然后转换成大写字母,在进行编码。
output = data.decode('ascii').upper().encode('ascii')
# 服务端发送消息给客户端。
sc.sendall(output)
# 计算接收到的字节长度
n += len(data)
print("接收的数据量为:",n)
# 强行刷新缓冲区。
sys.stdout.flush()
print('结束了')
# 回收套接字。
sc.close()
print(' Socket closed')
def client(host,port,bytecount):
# 定义一个套接字,同上边服务端。
sock = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
bytecount = (bytecount + 15) // 16 * 16
print("bytecount",bytecount)
# 定义一个十六个字节的字符串
message = b'capitalize this'
print('Sending ',bytecount,'bytes of data,in chunks of 16 bytes')
# 连接服务端。
sock.connect((host,port))
# 定义发送数量
sent = 0
while sent <= bytecount :
# 客户端发送消息
sock.sendall(message)
sent += len(message)
print("发送了多少数据:",sent)
# 强行刷新缓冲区
sys.stdout.flush()
# 最后发送一个结束符,告诉服务端发送结束了。
sock.sendall(b'efo')

print("结束了")
# 单向的socket便称为半开放Socket。要实现半开放式,需要用到shutdown()函数。
sock.shutdown(socket.SHUT_WR)
print('Receving all the data the server sends back')
# 定义接收到的字节变量
received = 0
while True:
# 用来接收服务端传回来的消息
data = sock.recv(42)
if not received :
# 打印第一次进来,接收到的数据
print(" The firse data received says",repr(data))
if not data:
break
# 计算接收到字节数的总和。
received += len(data)
print("接收的数据量为:",received)
print('结束了')
sock.close()

if __name__ == "__main__":
# 定义一个字典
choices = {'client':client,'server':server}
parser = argparse.ArgumentParser(description = 'Get deadlocked over TCP')
parser.add_argument('role',choices = choices,help = 'which role to play')
parser.add_argument('host',help = 'interface the server listens at;'
' host the client sends to')
parser.add_argument("bytecount",type = int,nargs ='?',default = 16,
help = 'number of bytes for client to send (default 16)')
parser.add_argument('-p',metavar = "PORT",type = int,default = 1060,help = "TCP port (default 1060")

args = parser.parse_args()
function = choices[args.role]
function(args.host,args.p,args.bytecount)

02_tcp_deadlock的更多相关文章

随机推荐

  1. 061 01 Android 零基础入门 01 Java基础语法 06 Java一维数组 08 一维数组总结

    061 01 Android 零基础入门 01 Java基础语法 06 Java一维数组 08 一维数组总结 本文知识点:一维数组总结 总结 注意点

  2. TCHAR数据类型介绍

    转载:https://blog.csdn.net/mousebaby808/article/details/5259944 并不是所有的Windows操作系统都支持UNICODE编码的API(例如早期 ...

  3. ElasticSearch 索引 VS MySQL 索引

    前言 这段时间在维护产品的搜索功能,每次在管理台看到 elasticsearch 这么高效的查询效率我都很好奇他是如何做到的. 这甚至比在我本地使用 MySQL 通过主键的查询速度还快. 为此我搜索了 ...

  4. Java之ConcurrentHashMap源码解析

    ConcurrentHashMap源码解析 目录 ConcurrentHashMap源码解析 jdk8之前的实现原理 jdk8的实现原理 变量解释 初始化 初始化table put操作 hash算法 ...

  5. antd pro 路由

    概要 antd pro 路由简介 路由, 菜单和面包屑 页面之间的路由 带参数的路由 总结 概要 路由配置是单页应用的核心之一, antd pro 将所有的路由配置集中在一个文件中, 可以更好的对应用 ...

  6. 解决VMware无法共享ubuntu虚拟机文件

    1.错误信息:无法更新运行时文件夹共享状态:在客户机操作系统内装载共享文件夹文件系统时出错 2.检查vmware tool是否正确安装 lsmod | grep vmhgfs modprobe vmh ...

  7. monolog封装

    做一下基本关于Monolog的基本介绍: Monolog是基于PHP的日志类库. 介绍就到这,言归正传 安装 安装最新版本:(composer 还没安装的~:https://www.phpcompos ...

  8. git merge 与 git rebase的区别?

    一,git merge 与 git rebase的区别 1,git merge 例如: master分支合并dev分支,git将两个分支dev和master上的所有commit , 按照提交时间的先后 ...

  9. docker的常用操作之三:网络配置

    一, docker安装后容器使用哪些网络类型? 在宿主机执行如下命令: [root@localhost liuhongdi]# docker network ls NETWORK ID NAME DR ...

  10. swoole 客户端和服务端不断通信

    server.php <?php class Chat { const HOST = '0.0.0.0';//ip地址 0.0.0.0代表接受所有ip的访问 const PART = 9501; ...