tcp介绍

引用百度百科的介绍

传输控制协议(TCP,Transmission Control Protocol)是一种面向连接的、可靠的、基于字节流的传输层通信协议,由IETF的RFC 793 [1] 定义。

TCP旨在适应支持多网络应用的分层协议层次结构。 连接到不同但互连的计算机通信网络的主计算机中的成对进程之间依靠TCP提供可靠的通信服务。TCP假设它可以从较低级别的协议获得简单的,可能不可靠的数据报服务。 原则上,TCP应该能够在从硬线连接到分组交换或电路交换网络的各种通信系统之上操作。

通常会将udp和tcp进行对比分析,之后再找时间用实例进行深入对比分析。现在先来看这张图,明白一下两者在实现上的差距。udp实现多人聊天室可以看这里。

因为tcp是基于连接的,所以必须先启动服务端,在通过客户端去连接服务端。

客户端

先来看客户端的代码,实现相对比较简单,利用两个线程或者是os.fork()创建子进程的方式,完成连接到服务器之后的发送/接收功能。

还是一样的指令操作模式

from socket import *

import os,sys,signal

import time

class tcpClient():

server_addr = ('127.0.0.1',9090)

def __init__(self,name):

self.sockfd = socket() # 创建套接字

self.user_name = name

def msg_recv(self):

while True:

data = self.sockfd.recv(1024)

if data.decode('gb2312') == 'exit':

print('客户端退出')

break

print(data.decode('gb2312'))

def msg_send(self): ##发送消息

while True:

data_info = input()

self.sockfd.send(data_info.encode('gb2312'))

if data_info == 'exit':

break

def start(self):

# 连接至服务器

try:

self.sockfd.connect(self.server_addr)

except Exception:

print("连接失败 请重试!")

self.sockfd.close()

return

# 判断是否成功进入聊天室

while True:

name = input("请输入用户名:")

self.sockfd.send((name+' -n').encode('gb2312'))

data = self.sockfd.recv(128)

print(data.decode('gb2312'),type(data.decode('gb2312') ))

if data.decode('gb2312') == 'OK':

print("你已经成功进入聊天室")

break

else:

print(data.decode('gb2312'))

signal.signal(signal.SIGCHLD,signal.SIG_IGN)

pid = os.fork()

if pid < 0:

sys.exit("err")

elif pid == 0: ##子进程

self.msg_recv()

else:

print('主进程pid为',pid)

self.msg_send()

if __name__=='__main__':

server1 = tcpClient('sam')

server1.start()

服务端

tcp只能一对一连接,而要实现多人聊天,就需要多线程进行协助。服务端主线程监听端口是否有客户端尝试连接,当有客户端连接时,创建新线程去完成对应客户端的相应工作、而多人聊天,即可以通过服务端的调配,实现对信息发送到目标客户端完成聊天功能。

from socket import *

from threading import Thread

import os,sys

import time

class Node():

def init(self):

self.Name = None

self.Ip = None

self.Thr = None

class tcpServer():

user_name = {} # dict 用户名:对象

jobs = {} # 存储线程对象

def __init__(self,post):

self.ServerPort = post

self.tcp_socket = socket() # tcp套接字

self.tcp_socket.setsockopt(SOL_SOCKET,SO_REUSEADDR,1) # 端口重用

self.tcp_socket.bind(self.ServerPort)

def start(self):

self.tcp_socket.listen(5)

print(self.getTime(),'系统:等待连接')

while True:

try:

conn,addr = self.tcp_socket.accept()

except KeyboardInterrupt:

self.tcp_socket.close()

sys.exit('\n'+self.getTime()+'系统:服务器安全退出')

except Exception as e:

print(e)

continue

t = Thread(target=self.do_request,args=(conn,))

t.start()

self.jobs[conn] = t

for c in self.jobs:

if c._closed is True:

self.jobs[c].join()

def do_request(self,conn):

connNode = Node()

while True:

recv_data = conn.recv(1024).decode('gb2312').strip()

dest_ip = conn.getpeername()

info_list = recv_data.split(' ') # 切割命令

if recv_data=='exit':

print(self.getTime()+' 系统:用户'+connNode.Name+'退出')

conn.send('exit'.encode('gb2312'))

self.user_name.pop(connNode.Name)

conn.close()

break

else:

try:

A = info_list[-2],info_list[-1]

except IndexError:

conn.send((self.getTime()+' 系统:无法识别您的指令,请重新输入!').encode('gb2312'))

continue

if info_list[-2]=='-t':

if info_list[-1] not in self.user_name.keys(): # 目前查询不到目标用户,向发送用户发起警告

data_info = self.getTime()+' 系统:发送失败!用户不存在!'

conn.send(data_info.encode('gb2312'))

continue

destNode = self.user_name[info_list[-1]] # 接收方端口

data_info = self.getTime()+'%s:'%connNode.Name+' '.join(info_list[:-2]) # 需发送的信息

print(self.getTime()+' 系统:%s发送信息给了%s'%(connNode.Name,info_list[-1]))

destNode.Thr.send(data_info.encode('gb2312'))

elif info_list[-1]=='-n':

# 新用户注册

print(self.getTime()+' 系统:'+info_list[0]+'连接成功')

data_info = self.getTime()+' 系统:'+info_list[0] + '加入了聊天'

self.sent_to_all(data_info)

conn.send('OK'.encode('gb2312'))

connNode.Name = info_list[0]

connNode.Ip = dest_ip

connNode.Thr = conn

self.user_name[info_list[0]] = connNode

elif info_list[-1]=='-ta':

# 群发消息

data_info = self.getTime()+'%s:'%connNode.Name+' '.join(info_list[:-1])

self.sent_to_all_notMe(connNode.Name,data_info)

def getTime(self):

return '['+time.strftime("%Y-%m-%d%H:%M:%S", time.localtime())+']'

def sent_to_all(self,data_info):

# 系统广播信息

print(self.getTime()+' 系统:群发信息给了',end = '')

for i in self.user_name.values():

print(i.Name+'、',end='')

i.Thr.send(data_info.encode('gb2312'))

print()

def sent_to_all_notMe(self,name,data_info):

# 广播消息除了指定用户

print(self.getTime()+' 系统:群发信息给了',end = '')

for i in self.user_name.values():

if i.Name!=name:

print(i.Name+'、',end='')

i.Thr.send(data_info.encode('gb2312'))

print()

if __name__=='__main__':

Host = '127.0.0.1'

Post = 9090

server1 = tcpServer((Host, Post))

server1.start()

- 如果有什么写错的地方,还请指导纠正! -

python多人聊天室 跨主机_python+tcp实现多人聊天室相关推荐

  1. python socket 网络聊天室_Python基于Socket实现简单聊天室

    本文实例为大家分享了Python基于Socket实现简单聊天室,供大家参考,具体内容如下 服务端 #!/usr/bin/env python # -*- coding: utf-8 -*- # @Ti ...

  2. TCP创建多人聊天室

    群聊-聊天室 群聊:任何时候,任何一个客户端都可以向其它客户端发送和接受数据,服务器只起到转发的作用. 1.首先创建一个聊天室的简易版(版本1). 需求:可以多个用户同时访问服务端,并且可以不断各自请 ...

  3. python聊天机器人源码_Python Google talk聊天机器人源码

    Python玩蛇网本文是关于依据xmpp封装的Jabber聊天机器人类. 并提供了Python Google talk聊天机器人源码供大家参考.这个python gtalk机器人是可以通过继承,并能重 ...

  4. python获取局域网在线主机_python通过scapy获取局域网所有主机mac地址示例

    python通过scapy获取局域网所有主机mac地址示例 发布于 2014-10-10 20:34:48 | 607 次阅读 | 评论: 0 | 来源: 网友投递 Python编程语言Python ...

  5. 基于阿里云用C/C++做了一个http协议与TCP协议的web聊天室的服务器——《干饭聊天室》

    基于阿里云用C/C++做了一个http协议与TCP协议的web聊天室的服务器--<干饭聊天室> 在这里首先感谢前端小伙伴飞鸟 前端技术请看一款基于React.C++,使用TCP/HTTP协 ...

  6. 视频教程-网络聊天室Java基础版(Socket_Swing编程)仿QQ聊天-Java

    网络聊天室Java基础版(Socket_Swing编程)仿QQ聊天 IT行业资深从业者,7年资深Java高级开发,Java架构师.曾就职银行.电信等行业多家上市公司.担任项目负责人,软件架构师.有丰富 ...

  7. calico跨主机ping不通_戳穿 Calico 的谎言

    前言 Calico 是一个纯三层的数据中心网络方案,而且无缝集成像 OpenStack 这种 Iaas 云架构,能够提供可控的 VM.容器.裸机之间的 IP 通信.为什么说它是纯三层呢?因为所有的数据 ...

  8. twisted:基于python的twisted框架编写一个客户端和服务端的对话聊天空间

    twisted:基于python的twisted框架编写一个客户端和服务端的对话聊天空间 目录 输出结果 实现代码 输出结果 更新-- 实现代码 #基于python的twisted框架编写一个简单的聊 ...

  9. Docker 跨主机网络方案分析

    PS:文章首发公众号,欢迎大家关注我的公众号:aCloudDeveloper,专注技术分享,努力打造干货分享平台,二维码在文末可以扫,谢谢大家. 上篇文章介绍了容器网络的单主机网络,本文将进一步介绍多 ...

最新文章

  1. Android华容道之一步一步实现-6-还原状态检测
  2. sql if else语句_一道sql题学习if语句和case when语句
  3. VC++ 6.0 中如何使用 CRT 调试功能来检测内存泄漏[转]
  4. repeater使用1
  5. 【重磅快讯】T11 2019数据智能技术峰会举办,AI将成为行业颠覆者
  6. 16 Managing Undo
  7. android for循环比大小,如何让for()循环花费更少的时间(android)?
  8. 技术人 | 是架构师,也是工作中的“厨师”
  9. Asp.net 5种页面转向方法 转载
  10. cruise软件模型,混动仿真模型,IMMD架构混联混动仿真模型,Cruise混动仿真模型,混联混动汽车动力性经济性仿真
  11. 太实用了 Python 合成多张图片到PDF格式
  12. python做马尔科夫模型预测法_Python 3 爬虫学习笔记 8 马尔科夫模型
  13. 字体设计 css_设计好CSS字体堆栈的三个步骤
  14. 【JS-05】javascript检测ie版本
  15. java实现物体下落效果_android仿微信表情雨下落效果的实现方法
  16. Qt sender()用法详解
  17. 浅谈二维码门禁在互联网的时代特色
  18. Android baidu地图定位实现签到打卡功能(附源码)
  19. Darknet - How to improve object detection? - 如何提升物体检测?
  20. 捷联惯导基础知识解析之四(粗/精对准和GPS/IMU和GPS/里程计组合导航)

热门文章

  1. 物联网毕设 -- 智能药箱提示系统(GSM+GPRS+APP+OneNet)
  2. iOS后台运行NSTimer
  3. 51Nod 1535 思维+DFS
  4. mpAndroidChart 柱状图一览(中文斜体,横向柱状图,叠层柱状图,固定宽度左右滑动)
  5. 整合SpringSecurity OAuth2 JWT (附原因)一步步来如此简单
  6. 张宴的博客nginx+php+mysql搭建篇
  7. 1 Python中 _的作用
  8. Zabbix 监控 CPU 使用率
  9. Android控件——ViewFlipper的使用,垂直滚动广告条
  10. Fragment交互,接口方式从一个Fragment传参到另一个Fragment