转载自:https://www.cnblogs.com/wuxie1989/p/7204887.html

python socket编程 实现简单p2p聊天程序

目标是写一个python的p2p聊天的项目,这里先说一下python socket的基础课程

一、Python Socket 基础课程

  Socket就是套接字,作为BSD UNIX的进程通信机制,取后一种意思。通常也称作"套接字",用于描述IP地址和端口,是一个通信链的句柄,可以用来实现不同虚拟机或不同计算机之间的通信。在Internet上的主机一 般运行了多个服务软件,同时提供几种服务。每种服务都打开一个Socket,并绑定到一个端口上,不同的端口对应于不同的服务。Socket正如其英文原 意那样,像一个多孔插座。一台主机犹如布满各种插座的房间,每个插座有一个编号,有的插座提供220伏交流电, 有的提供110伏交流电,有的则提供有线电视节目。 客户软件将插头插到不同编号的插座,就可以得到不同的服务

  

Socket连接的步骤

(1)服务器监听:是服务器端套接字并不定位具体的客户端套接字,而是处于等待连接的状态,实时监控网络状态。

(2)客户端请求:是指由客户端的套接字提出连接请求,要连接的目标是服务器端的套接字。为此,客户端的套接字必须首先描述它要连接的服务器的套接字,指出服务器端套接字的地址和端口号,然后就向服务器端套接字提出连接请求。

(3)连接确认:是指当服务器端套接字监听到或者说接收到客户端套接字的连接请求,它就响应客户端套接字的请求,建立一个新的线程,把服务器端套接 字的描述发给客户端,一旦客户端确认了此描述,连接就建立好了。而服务器端套接字继续处于监听状态,继续接收其他客户端套接字的连接请求。

二、服务端程序

因为很喜欢看三体,所以这个服务端就起名叫红岸,红岸基地的主要作用就是作为server端来使用,转发双方的通信,现在是调试阶段,先使用socket写单线程的,以后会使用socketserver或者多线程来重新写一个

先建立一个连接列表

# -*- coding: utf-8 -*-
import select
import socketinBufSize = 4096
outBufSize = 4096
CONNECTION_LIST = []

构造函数

    def __init__(self,port=5247):# todo 使用socketserver来写self.serverSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)self.serverSocket.bind(('', port))self.serverSocket.listen(5)print "server wait for connect...."self.socketsMap = {}  # socket session字典 id : socketself.idMap = {} #socket session 字典 socket:idCONNECTION_LIST.append(self.serverSocket)

socketsMap和idMap是分别建立这id和socket之间的对应字典,P2P聊天的时候通过socket来找发送者id和通过接受者id来找socket

主要的处理函数是这样的

    def socet_handle(self):while 1:# Get the list sockets which are ready to be read through selectread_sockets, write_sockets, error_sockets = select.select(CONNECTION_LIST, [], [])for sock in read_sockets:# New connectionif sock == self.serverSocket:#用户通过主socket(即服务器开始创建的 socket,一直处于监听状态)来登录# Handle the case in which there is a new connection recieved through server_socketsockfd, addr = self.serverSocket.accept()id = sockfd.recv(100)self.login(id,sockfd)else:self.chat(sock)

通过select来监听所有的连接,select是一个非阻塞的监听程序,监听文件的读,写,错误,函数用法是select.select(readable_iterable,writeble_iterable,error_iterable,timeout).

如果用户是使用主socket(一直在监听的端口,用户登录时要连接到这个端口,然后再在别的端口通信),就要登录函数

登录函数如下

    def login(self,id,sock):#新用户登录print "%s login"%idself.socketsMap[id] = sockself.idMap[sock] = idsock.send('hello %s,you login successed'%id)CONNECTION_LIST.append(sock)#要在这里把socket加进来才行

在CONNECTION_LIST中把会话加进去,然后返回一个问候信息

聊天和广播程序

    def chat(self,sock):#点对点聊天,发送消息格式id||信息try:data = sock.recv(inBufSize)except Exception:sock.send("remote is offline")sock.close()else:remote_id = data.split('||')[0]message = data.split('||')[1]print "id = %s,message = %s"%(remote_id,message)local_id = self.idMap[sock]if remote_id == 'all':self.broadcast(local_id,message)else:self.p2psend(local_id,message,remote_id)def p2psend(self,local_id,message,remote_id):remote_socket = self.socketsMap[remote_id]message_send = "%s said : %s" % (local_id, message)try:remote_socket.sendall(message_send)except Exception,e:print eremote_socket.close()CONNECTION_LIST.remove(remote_socket)def broadcast(self,local_id,message):for sock in CONNECTION_LIST:if sock == self.serverSocket:continueelse:try:message_send = "%s said : %s" % (local_id, message)sock.send(message_send)except Exception,e:print esock.close()CONNECTION_LIST.remove(sock)continue

服务端的完全体如下

# -*- coding: utf-8 -*-
import select
import socketinBufSize = 4096
outBufSize = 4096
CONNECTION_LIST = []class ChatServer:def __init__(self,port=5247):# todo 使用socketserver来写self.serverSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)self.serverSocket.bind(('', port))self.serverSocket.listen(5)print "server wait for connect...."self.socketsMap = {}  # socket session字典 id : socketself.idMap = {} #socket session 字典 socket:id
        CONNECTION_LIST.append(self.serverSocket)def login(self,id,sock):#新用户登录print "%s login"%idself.socketsMap[id] = sockself.idMap[sock] = idsock.send('hello %s,you login successed'%id)CONNECTION_LIST.append(sock)#要在这里把socket加进来才行def chat(self,sock):#点对点聊天,发送消息格式id||信息try:data = sock.recv(inBufSize)except Exception:sock.send("remote is offline")sock.close()else:remote_id = data.split('||')[0]message = data.split('||')[1]print "id = %s,message = %s"%(remote_id,message)local_id = self.idMap[sock]if remote_id == 'all':self.broadcast(local_id,message)else:self.p2psend(local_id,message,remote_id)def p2psend(self,local_id,message,remote_id):remote_socket = self.socketsMap[remote_id]message_send = "%s said : %s" % (local_id, message)try:remote_socket.sendall(message_send)except Exception,e:print eremote_socket.close()CONNECTION_LIST.remove(remote_socket)def broadcast(self,local_id,message):for sock in CONNECTION_LIST:if sock == self.serverSocket:continueelse:try:message_send = "%s said : %s" % (local_id, message)sock.send(message_send)except Exception,e:print esock.close()CONNECTION_LIST.remove(sock)continuedef socet_handle(self):while 1:# Get the list sockets which are ready to be read through selectread_sockets, write_sockets, error_sockets = select.select(CONNECTION_LIST, [], [])for sock in read_sockets:# New connectionif sock == self.serverSocket:#用户通过主socket(即服务器开始创建的 socket,一直处于监听状态)来登录# Handle the case in which there is a new connection recieved through server_socketsockfd, addr = self.serverSocket.accept()id = sockfd.recv(100)self.login(id,sockfd)else:self.chat(sock)def main(self):self.socet_handle()self.serverSocket.close()if __name__ == '__main__':chat_server_obj = ChatServer()chat_server_obj.main()

三、客户端程序

客户端程序的名字是叶文洁和监听员1379,不要回答!不要回答!不要回答!

主要就是使用select来监听sys.stdin和socket,来活儿了就要及时处理

    def socket_handler(self):while 1:rlist = [sys.stdin, self.client_socket]  # 接收列表read_list, write_list, error_list = select.select(rlist, [], [], 2)for sock in read_list:# incoming message from remote serverif sock == self.client_socket:data = sock.recv(4096)if not data:print '\nDisconnected from chat server'sys.exit()else:# print data
                        sys.stdout.write(data)self.prompt()# user entered a messageelse:msg = sys.stdin.readline()remote_id = raw_input("Please input remote id:")msg_send = "%s||%s"%(remote_id,msg)self.client_socket.send(msg_send)self.prompt()

快吃中午饭了,就不详细说了,也没什么好详细说的,很简单,客户端完全体如下,叶文洁的id是1,监听员1379的id是2,后边可以改成手动指定的,在群聊里面加上托马斯维德和程心

# -*- coding:utf-8 -*-
import socket, select, string, sys
HOST = '127.0.0.1'
PORT = 5247
ID = '1'class ChatClient:def __init__(self):self.client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)self.client_socket.settimeout(2)self.connect()def connect(self):try:self.client_socket.connect((HOST, PORT))self.client_socket.send(ID)except Exception,e:print 'Unable to connect because of %s'%esys.exit()else:print 'Connected to remote host. Start sending messages'self.prompt()def prompt(self):sys.stdout.write('\n<You> ')sys.stdout.flush()def socket_handler(self):while 1:rlist = [sys.stdin, self.client_socket]  # 接收列表read_list, write_list, error_list = select.select(rlist, [], [], 2)for sock in read_list:# incoming message from remote serverif sock == self.client_socket:data = sock.recv(4096)if not data:print '\nDisconnected from chat server'sys.exit()else:# print data
                        sys.stdout.write(data)self.prompt()# user entered a messageelse:msg = sys.stdin.readline()remote_id = raw_input("Please input remote id:")msg_send = "%s||%s"%(remote_id,msg)self.client_socket.send(msg_send)self.prompt()if __name__ == '__main__':chat_client_obj = ChatClient()chat_client_obj.socket_handler()

githu地址

https://github.com/wuxie2015/tri_body_chat

聊天效果如下

很惭愧,只做了一点微小的工作

python socket编程 实现简单p2p聊天程序相关推荐

  1. python实现简易聊天需要登录_python socket编程 实现简单p2p聊天程序

    目标是写一个python的p2p聊天的项目,这里先说一下python socket的基础课程 一.Python Socket 基础课程 Socket就是套接字,作为BSD UNIX的进程通信机制,取后 ...

  2. Socket编程实践(3) 多连接服务器实现与简单P2P聊天程序例程

    SO_REUSEADDR选项 在上一篇文章的最后我们贴出了一个简单的C/S通信的例程.在该例程序中,使用"Ctrl+c"结束通信后,服务器是无法立即重启的,如果尝试重启服务器,将被 ...

  3. Java网络编程以及简单的聊天程序

    网络编程技术是互联网技术中的主流编程技术之一,懂的一些基本的操作是非常必要的.这章主要讲解网络编程,UDP和Socket编程,以及使用Socket做一个简单的聊天软件. 全部代码下载:链接 1.网络编 ...

  4. python写机器人程序_用Python写的一个多线程机器人聊天程序

    本人是从事php开发的, 近来想通过php实现即时通讯(兼容windows).后来发现实现起来特别麻烦, 就想到python.听说这家伙在什么地方都能发挥作用.所以想用python来做通讯模块...所 ...

  5. Python Socket 编程——聊天室示例程序

    上一篇 我们学习了简单的 Python TCP Socket 编程,通过分别写服务端和客户端的代码了解基本的 Python Socket 编程模型.本文再通过一个例子来加强一下对 Socket 编程的 ...

  6. 通信软件基础B-重庆邮电大学-Java-编程实现一个简单的聊天程序-多线程编程实现

    实验任务六 编程实现一个简单的聊天程序-多线程编程实现 1. 系统设计要求 编程实现一个简单的聊天程序,实现两台计算机间的信息交互,使用多线程编程实现:可同时连接多个客户端,服务器收到客户端发送的消息 ...

  7. C#编写简单的聊天程序

    原文:http://www.tracefact.net/CSharp-Programming/Simple-Chat.aspx 引言 这是一篇基于Socket进行网络编程的入门文章,我对于网络编程的学 ...

  8. 简单网络聊天程序java_基于Java实现hello/hi简单网络聊天程序

    Socket简要阐述 Socket的概念 Socket的英文原义是"孔"或"插座". 在网络编程中,网络上的两个程序通过一个双向的通信连接实现数据的交换,这个连 ...

  9. python socket 实现的简单http服务器

    看这篇文章挺简约的收藏下,只需要替换reg.html  action  http://192.168.56.188:8000   为/ 即可不用改ip地址  post时 预备知识: 关于http 协议 ...

最新文章

  1. IT阅读——关于“业务”
  2. byte数组添加数据_数据类型
  3. 如何使用ggplot2绘制左右分布的柱状图
  4. 【openfst样例2】Downcasing Text
  5. centos6.5搭建lnmp环境
  6. Spring WebClient vs. RestTemplate
  7. 深js, jsconf China 回顾
  8. 绑定dictionary 给定关键字不再字典中_VBA代码集锦-利用字典做两列数据的对比并对齐...
  9. OLAP引擎:基于Druid组件进行数据统计分析
  10. pymysql连接mysql数据库try_pymysql 连接数据库和基本使用
  11. 使用值类型LazyString分析字符串
  12. Flink-1.13集成hudi-0.10.0
  13. pgAdmin III简介
  14. win10安装Dreamweaver cc 2019报无法写入注册表的错误
  15. Instrument详解
  16. wsl2使用vscode无法写入文件permission denied解决方法
  17. jdbc写入数据库乱码问题
  18. 谷歌扩展工具下载网址---最新
  19. [Copy] Netlink Socket
  20. 某同步总线的时钟频率为100MHz,宽度为32位,地址/数据线复用,每传输一个地址或者数据就占用一个时钟周期。该总线支持猝发传输方式,则一次“主存写”总线事务传输128位数据所需的时间至少是

热门文章

  1. 为什么要用RSocket
  2. linux与linux驱动
  3. Frustum culling
  4. 4D毫米波雷达硬件系统架构
  5. MySQL——建表建库基本命令
  6. mysql锁表原因及解决
  7. fedora下载工具
  8. go开源网络库nano(6)-hander逻辑
  9. 海淀服务器维修,服务器维修服务器维修防御升级、数据恢复、对接出错等维修服务...
  10. IKEv2的认证数据生成过程