多线程tcp  server & client

tcp服务端(多线程):

  1. from socket import *
  2. from threading import Thread
  3.  
  4. def client(socket_client, msg_addr):
  5. print(">>>有新客户端连接<<<")
  6. try:
  7. while True:
  8. # 接受客户端发来的信息
  9. msg = socket_client.recv(1024)
  10. if msg:
  11. print("%s--> %s" % (msg_addr, msg.decode('utf-8')))
  12. else:
  13. print(msg_addr)
  14. print("客户端已断开连接...")
  15. break
  16. except:
  17. socket_client.close()
  18.  
  19. def main():
  20. #建立一个套接字, AF_INET 表示遵从IPv4协议,SOCK_STREAM(流) 表示使用的是tcp协议传输
  21. # 若使用UDP协议传输, 则使用SOCK_DGRAM(数据报)
  22. server = socket(AF_INET, SOCK_STREAM)
  23.  
  24. # 重复使用绑定的信息
  25. # 此处若服务端成为tcp四次挥手的第一次,那么服务端最后将等待 2MSL 的时间来接受客户端可能发来的ack
  26. # 在这段时间内,若服务器想重复执行,之前被占用的端口等服务不被释放,导致服务器不能被执行
  27. #此处加上这句话则解决了这个问题
  28. server.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)
  29.  
  30. msg_server = ("localhost", 7788)
  31. # 绑定本地的7788端口
  32. server.bind(msg_server)
  33. #开始监听
  34. #此处的listen中的值表示处于半连接和以连接状态的client总和
  35. server.listen(5)
  36. try:
  37. while True:
  38. #与客户端建立连接
  39. # socket_client表示为这个客户端创建出了包含tcp三次握手信息的新的套接字
  40. # msg_addr 包含这个客户端的信息
  41. socket_client, msg_addr = server.accept()
  42. #为每一个连接服务端的客户端创建出一个单独的线程,并传入上面的两个参数
  43. t = Thread(target=client, args=(socket_client,msg_addr))
  44. #在多线程中,创建的socket都共用一个socket_client,所以此时这个套接字不能被关闭
  45. #线程只是在cpu的某一个核心中不断的重复切换调用函数而已,所以数据其实都是一份,也是多线程中的数据可以共享的原因
  46. t.start()
  47.  
  48. finally:
  49. server.close()
  50.  
  51. if __name__ == "__main__":
  52. main()

tcp服务端(多进程):

  1. from socket import *
  2. from multiprocessing import *
  3.  
  4. def client(socket_client, msg_addr):
  5. print(">>>有新客户端连接<<<")
  6. try:
  7. while True:
  8. msg = socket_client.recv(1024)
  9. if msg:
  10. print("%s--> %s" % (msg_addr, msg.decode('utf-8')))
  11. else:
  12. print(msg_addr)
  13. print("客户端已断开连接...")
  14. break
  15. except:
  16. socket_client.close()
  17.  
  18. def main():
  19. server = socket(AF_INET, SOCK_STREAM)
  20. server.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)
  21.  
  22. msg_server = ("localhost", 7788)
  23.  
  24. server.bind(msg_server)
  25.  
  26. server.listen(5)
  27. try:
  28. while True:
  29. socket_client, msg_addr = server.accept()
  30. t = Process(target=client, args=(socket_client,msg_addr))
  31. #创建一个子进程时,会向子进程中复制一份资源,所以主进程中的套接字可以关闭
  32. #在多进程中,创建一个进程即表示占用某一个cpu的资源,创建的进程比较多时,这些进程就会在cpu之间轮流占用
  33. t.start()
  34. socket_client.close()
  35.  
  36. finally:
  37. server.close()
  38.  
  39. if __name__ == "__main__":
  40. main()

tcp客户端:

  1. from socket import *
  2.  
  3. client = socket(AF_INET,SOCK_STREAM)
  4.  
  5. server_msg = ("localhost",7788)
  6. #连接服务器
  7. client.connect(server_msg)
  8.  
  9. while True:
  10. send = input("要发送的文本内容:")
  11. if send == 'q':
  12. break
  13.  
  14. else:
  15. client.send((send).encode("utf-8"))
  16. print("发送成功!")
  17.  
  18. client.close()

关于tcp通信过程中的三次握手、四次挥手的过程

三次握手:

此过程中:

第一次握手,客户端先发一个SYN请求并附带一个J的值给服务端

第二次握手,服务端收到请求后解堵塞,发送一个SYN请求并附带一个K值,还发送了第一次握手后对客户端的响应包并附带在之前接收到的J值的基础上加上1,即J+1

第三次握手,客户端收到服务端发来的SYN请求和K值后,再发送一个K+1的响应包给服务端

至此,三次握手成功完成,客户端和服务端之间成功建立tcp链接

四次挥手:

此过程中:

第一次挥手:客户端调用了close,发送一个结束请求附带一个x+2的值,和一个y+1的响应包给服务端

第二次挥手:服务端发送x+3的响应包给客户端(其实每次的响应包的附带值都是在之前接收到的seq的值上加上1的结果)

第三次挥手:服务端调用close,发送一个结束seq附带一个y+1的值给客户端,此时服务端成功断开连接

第四次挥手:客户端接收到服务端的响应包和FIN请求后,回递一个y+2的响应包给服务端,此时的客户端进入time_wait状态,即继续等待2MSL的时间再完全断开链接(至于为什么要等待2MSL的时间,请看下文的MSL详解     ^_^     )

要点:在四次挥手的过程中,哪一方先调用close, 哪一方就会在第三次挥手后继续等待2MSL的时间

tcp通信过程中的2MSL的问题:

2MSL即为在四次挥手的第三次过程中,先发起中断连接的一方将会继续等待2倍的MSL时间后再完全中断tcp连接

MSL即为一个数据包在网络上存活的最长时间,即数据包从被发送到被接收所经历的最长时间

等待2倍的MSL时间就是因为防止服务端没收到最后一次的ACK,即在2MSL的时间内,若服务端没收到最后的ACK,在超时时间(MSL)后,服务端会认为客户端没收到第三次挥手中的FIN,这时服务端会再发一份FIN,这时一共经历了2MSL的时间,而客户端此时等待了2MSL的时间,正好可以接收这一次服务端重发的FIN请求,从而有效的保证了所有的请求和回应都会被对方接收

多线程实现tcp聊天服务器的更多相关文章

  1. Node创建TCP聊天

    //创建新的tcp服务器var net = require('net');var chatServer = net.createServer()chatServer.on('connection',f ...

  2. 通过python 构建一个简单的聊天服务器

    构建一个 Python 聊天服务器 一个简单的聊天服务器 现在您已经了解了 Python 中基本的网络 API:接下来可以在一个简单的应用程序中应用这些知识了.在本节中,将构建一个简单的聊天服务器.使 ...

  3. 看完这篇包你进大厂,实战即时聊天,一文说明白:聊天服务器+聊天客户端+Web管理控制台。

    一.前言 说实话,写这个玩意儿是我上周刚刚产生的想法,本想写完后把代码挂上来赚点积分也不错.写完后发现这东西值得写一篇文章,授人予鱼不如授人以渔嘛(这句话是这么说的吧),顺便赚点应届学生MM的膜拜那就 ...

  4. [CareerCup] 8.7 Chat Server 聊天服务器

    8.7 Explain how you would design a chat server. In particular, provide details about the various bac ...

  5. 定制的Server-Sent Events 聊天服务器

    //匿名聊天服务器 //将新的消息POST到/chat地址,或者以GET形式从通一个URL获取文本或事件流 //创建一个GET请求到"/"来返回一个简单的HTML文件,这个文件包括 ...

  6. Socket 基础解析使用ServerSocket建立聊天服务器

    很简单的教程哦! 1.socket 简介 Socket 又称"套接字",应用程序通常通过"套接字"向网络发出请求或者应答网络请求.ServerSocket 用于 ...

  7. Javascript多线程引擎(十)---Web服务器

     Javascript多线程引擎(十)---Web服务器 经过一天的努力, 引擎可以支持web服务的功能了并且支持UTF-8的编码, 具有对HTTP参数的解析,状态码的配置, 响应报文的输出等. 提供 ...

  8. openfire:基于开源 Openfire 聊天服务器 - 开发Openfire聊天记录插件

    基于开源 Openfire 聊天服务器 - 开发Openfire聊天记录插件 上一篇文章介绍到怎么在自己的Java环境中搭建openfire插件开发的环境,同时介绍到怎样一步步简单的开发openfir ...

  9. 【unix网络编程第三版】阅读笔记(四):TCP客户/服务器实例

    本篇博客主要记录一个完整的TCP客户/服务器实例的编写,以及从这个实例中引发的对僵死进程的处理等问题. 1. TCP客户/服务器功能需求 本实例完成以下功能: (1) 客户从标准输入读入一行文本,并写 ...

随机推荐

  1. form和table的区别

    转自:http://www.360doc.com/content/11/0108/14/5416196_84975265.shtml html中form表示一个表单,用来把一系列的控件包围起来,然后再 ...

  2. HDU6035 Colorful Tree

    题目链接:https://vjudge.net/problem/HDU-6035 题目大意: 多样例输入. 对于每一个样例,给出 n \((2 \le n \le 200000)\) 个结点的一棵树, ...

  3. 关于VMware问题:无法获得 VMCI 驱动程序的版本: 句柄无效。驱动程序“vmci.sys”的版本不正确

    有的童鞋可能安装虚拟机时出现了下边这样的错误,莫慌,下面咋们来解决!!! 1.首先,找到你的安装虚拟机的目录下有一个.vmx的文件 找到这个文件,用编辑器打开,将该值改为FALSE即可!

  4. Hive 集成 Hudi 实践(含代码)| 可能是全网最详细的数据湖系列

    公众号后台越来越多人问关于数据湖相关的内容,看来大家对新技术还是很感兴趣的.关于数据湖的资料网络上还是比较少的,特别是实践系列,对于新技术来说,基础的入门文档还是很有必要的,所以这一篇希望能够帮助到想 ...

  5. [PHP学习教程 - 心得]001.偷龙转凤技巧10则(Remember Tips)

    引言:PHP当中的一些猬锁技巧,比较基础,想起就发贴总结一下,老鸟换个姿势飘过去就是. [技巧]应该属于“方法”的一个范畴,主要指对一种生活或工作方法的熟练和灵活运用.[五笔]RFAG. 话不多说,下 ...

  6. UDP和TCP 简单 区别

    1.双方都是一种网络传输协议2.TCP需要建立连接,而UDP不需要建立连接(无连接传输)3.是否建立真实连接的特性,造成了双方可靠性的差距. @1 TCP属于可靠的传输协议:因为传输前双方建立好了连接 ...

  7. SpringBoot返回html页面

    一般Controller返回数据或页面,今天谈一下返回页面的场景. 一.不使用template 1. controller中定义对应的访问路由及返回的页面(使用Controller,不要使用RestC ...

  8. Redis 入门到分布式 (一)Redis初识

    个人博客网:https://wushaopei.github.io/    (你想要这里多有) 一.Redis特性目录 Redis的特性: 速度快 持久化 多种数据结构 支持多种编辑语言 功能丰富 简 ...

  9. Java实现 LeetCode 824 山羊拉丁文(暴力)

    824. 山羊拉丁文 给定一个由空格分割单词的句子 S.每个单词只包含大写或小写字母. 我们要将句子转换为 "Goat Latin"(一种类似于 猪拉丁文 - Pig Latin ...

  10. Java实现 洛谷 P1579 哥德巴赫猜想(升级版)

    题目背景 1742年6月7日哥德巴赫写信给当时的大数学家欧拉,正式提出了以下的猜想:任何一个大于9的奇数都可以表示成3个质数之和.质数是指除了1和本身之外没有其他约数的数,如2和11都是质数,而6不是 ...