多线程实现tcp聊天服务器
多线程tcp server & client
tcp服务端(多线程):
from socket import *
from threading import Thread def client(socket_client, msg_addr):
print(">>>有新客户端连接<<<")
try:
while True:
# 接受客户端发来的信息
msg = socket_client.recv(1024)
if msg:
print("%s--> %s" % (msg_addr, msg.decode('utf-8')))
else:
print(msg_addr)
print("客户端已断开连接...")
break
except:
socket_client.close() def main():
#建立一个套接字, AF_INET 表示遵从IPv4协议,SOCK_STREAM(流) 表示使用的是tcp协议传输
# 若使用UDP协议传输, 则使用SOCK_DGRAM(数据报)
server = socket(AF_INET, SOCK_STREAM) # 重复使用绑定的信息
# 此处若服务端成为tcp四次挥手的第一次,那么服务端最后将等待 2MSL 的时间来接受客户端可能发来的ack
# 在这段时间内,若服务器想重复执行,之前被占用的端口等服务不被释放,导致服务器不能被执行
#此处加上这句话则解决了这个问题
server.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1) msg_server = ("localhost", 7788)
# 绑定本地的7788端口
server.bind(msg_server)
#开始监听
#此处的listen中的值表示处于半连接和以连接状态的client总和
server.listen(5)
try:
while True:
#与客户端建立连接
# socket_client表示为这个客户端创建出了包含tcp三次握手信息的新的套接字
# msg_addr 包含这个客户端的信息
socket_client, msg_addr = server.accept()
#为每一个连接服务端的客户端创建出一个单独的线程,并传入上面的两个参数
t = Thread(target=client, args=(socket_client,msg_addr))
#在多线程中,创建的socket都共用一个socket_client,所以此时这个套接字不能被关闭
#线程只是在cpu的某一个核心中不断的重复切换调用函数而已,所以数据其实都是一份,也是多线程中的数据可以共享的原因
t.start() finally:
server.close() if __name__ == "__main__":
main()
tcp服务端(多进程):
from socket import *
from multiprocessing import * def client(socket_client, msg_addr):
print(">>>有新客户端连接<<<")
try:
while True:
msg = socket_client.recv(1024)
if msg:
print("%s--> %s" % (msg_addr, msg.decode('utf-8')))
else:
print(msg_addr)
print("客户端已断开连接...")
break
except:
socket_client.close() def main():
server = socket(AF_INET, SOCK_STREAM)
server.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1) msg_server = ("localhost", 7788) server.bind(msg_server) server.listen(5)
try:
while True:
socket_client, msg_addr = server.accept()
t = Process(target=client, args=(socket_client,msg_addr))
#创建一个子进程时,会向子进程中复制一份资源,所以主进程中的套接字可以关闭
#在多进程中,创建一个进程即表示占用某一个cpu的资源,创建的进程比较多时,这些进程就会在cpu之间轮流占用
t.start()
socket_client.close() finally:
server.close() if __name__ == "__main__":
main()
tcp客户端:
from socket import *
client = socket(AF_INET,SOCK_STREAM)
server_msg = ("localhost",7788)
#连接服务器
client.connect(server_msg)
while True:
send = input("要发送的文本内容:")
if send == 'q':
break
else:
client.send((send).encode("utf-8"))
print("发送成功!")
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聊天服务器的更多相关文章
- Node创建TCP聊天
//创建新的tcp服务器var net = require('net');var chatServer = net.createServer()chatServer.on('connection',f ...
- 通过python 构建一个简单的聊天服务器
构建一个 Python 聊天服务器 一个简单的聊天服务器 现在您已经了解了 Python 中基本的网络 API:接下来可以在一个简单的应用程序中应用这些知识了.在本节中,将构建一个简单的聊天服务器.使 ...
- 看完这篇包你进大厂,实战即时聊天,一文说明白:聊天服务器+聊天客户端+Web管理控制台。
一.前言 说实话,写这个玩意儿是我上周刚刚产生的想法,本想写完后把代码挂上来赚点积分也不错.写完后发现这东西值得写一篇文章,授人予鱼不如授人以渔嘛(这句话是这么说的吧),顺便赚点应届学生MM的膜拜那就 ...
- [CareerCup] 8.7 Chat Server 聊天服务器
8.7 Explain how you would design a chat server. In particular, provide details about the various bac ...
- 定制的Server-Sent Events 聊天服务器
//匿名聊天服务器 //将新的消息POST到/chat地址,或者以GET形式从通一个URL获取文本或事件流 //创建一个GET请求到"/"来返回一个简单的HTML文件,这个文件包括 ...
- Socket 基础解析使用ServerSocket建立聊天服务器
很简单的教程哦! 1.socket 简介 Socket 又称"套接字",应用程序通常通过"套接字"向网络发出请求或者应答网络请求.ServerSocket 用于 ...
- Javascript多线程引擎(十)---Web服务器
Javascript多线程引擎(十)---Web服务器 经过一天的努力, 引擎可以支持web服务的功能了并且支持UTF-8的编码, 具有对HTTP参数的解析,状态码的配置, 响应报文的输出等. 提供 ...
- openfire:基于开源 Openfire 聊天服务器 - 开发Openfire聊天记录插件
基于开源 Openfire 聊天服务器 - 开发Openfire聊天记录插件 上一篇文章介绍到怎么在自己的Java环境中搭建openfire插件开发的环境,同时介绍到怎样一步步简单的开发openfir ...
- 【unix网络编程第三版】阅读笔记(四):TCP客户/服务器实例
本篇博客主要记录一个完整的TCP客户/服务器实例的编写,以及从这个实例中引发的对僵死进程的处理等问题. 1. TCP客户/服务器功能需求 本实例完成以下功能: (1) 客户从标准输入读入一行文本,并写 ...
随机推荐
- Jquery获取select option动态添加自定义属性值失效
Jquery获取select option动态添加自定义属性值失效 2014/12/31 11:49:19 中国学网转载 编辑:李强 http://www.xue163.com/588880/3909 ...
- VueRouter小手册
目录 一. 了解router 二. 工作流程 三. 简单的Demo 四. 理解template和route的组合 五. Vue-Router-GoBack记录返回 六. Router-Link 七. ...
- Gym101635K Blowing Candles
题目链接:http://codeforces.com/gym/101635 题目大意: 推荐一篇文章:https://blog.csdn.net/wang_heng199/article/detail ...
- 二、工具类ImageUtil——图片处理
这个工具类完成的工作如下: 1.第一个static方法,完成图片格式的转换.统一转换成.jpg格式. package util; import java.awt.Toolkit; import jav ...
- 关闭 WordPress 自动更新
# 方法一 推荐!编辑 WordPress 网站目录下的 wp-config.php 文件,添加如下代码: define( 'AUTOMATIC_UPDATER_DISABLED', true ); ...
- 2.Redis安装和简单使用
(1)安装Redis Redis目前只支持Linux系统,因为开发此软件的创始者认为,Redis是为后台数据服务的,所以认为该软件使用在纯净的服务环境下,而不是应用型操作系统下,而Linux作为服务器 ...
- [PHP学习教程 - 网络]001.下载/采集远程文件到本地(Download File)
引言:如何把http://mzitu.com里的图片全部下载下来呢? 一身浩然正气的AC陷入的深思.... 当然这里涉及到的功能有线程,网页请求,页面提取,下载图片等等.今天,我们先讲一下如何下载文件 ...
- 枚举&注解
枚举:自定义枚举类 使用Enum关键字定义的枚举类 注解:jdk内置的基本注解类型(3个) 自定义注解类型 对注解进行注解(元注解4个) 利用反射获取注解信息(反射部分涉及) 自定义枚举类: Test ...
- nvm的安装,安装node,npm
先说说我为什么使用nvm吧 最近在搞react-native,就碰到了很多坑,其中就有node带来的坑,当你运行react-native start (这是rn启动服务器的命令)就会报一个正则的错误, ...
- # # # Vue的分环境打包
我们使用Vue-cli的默认环境是只有dev和prod两种环境,在开发中我们的项目一般是开发版.测试版.pre版.Prod版.我们一般是在源码中API地址中修改后然后打包. ###1.首先安装cros ...