目标是写一个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 -*-

importselectimportsocket

inBufSize= 4096outBufSize= 4096CONNECTION_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 : socket

self.idMap = {} #socket session 字典 socket:id

CONNECTION_LIST.append(self.serverSocket)

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

主要的处理函数是这样的

defsocet_handle(self):while 1:#Get the list sockets which are ready to be read through select

read_sockets, write_sockets, error_sockets =select.select(CONNECTION_LIST, [], [])for sock inread_sockets:#New connection

if sock == self.serverSocket:#用户通过主socket(即服务器开始创建的 socket,一直处于监听状态)来登录

#Handle the case in which there is a new connection recieved through server_socket

sockfd, 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"%id

self.socketsMap[id]=sock

self.idMap[sock]=id

sock.send('hello %s,you login successed'%id)

CONNECTION_LIST.append(sock)#要在这里把socket加进来才行

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

聊天和广播程序

def chat(self,sock):#点对点聊天,发送消息格式id||信息

try:

data=sock.recv(inBufSize)exceptException:

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)defp2psend(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)exceptException,e:printe

remote_socket.close()

CONNECTION_LIST.remove(remote_socket)defbroadcast(self,local_id,message):for sock inCONNECTION_LIST:if sock ==self.serverSocket:continue

else:try:

message_send= "%s said : %s" %(local_id, message)

sock.send(message_send)exceptException,e:printe

sock.close()

CONNECTION_LIST.remove(sock)continue

服务端的完全体如下

#-*- coding: utf-8 -*-

importselectimportsocket

inBufSize= 4096outBufSize= 4096CONNECTION_LIST=[]classChatServer: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 : socket

self.idMap = {} #socket session 字典 socket:id

CONNECTION_LIST.append(self.serverSocket)def login(self,id,sock):#新用户登录

print "%s login"%id

self.socketsMap[id]=sock

self.idMap[sock]=id

sock.send('hello %s,you login successed'%id)

CONNECTION_LIST.append(sock)#要在这里把socket加进来才行

def chat(self,sock):#点对点聊天,发送消息格式id||信息

try:

data=sock.recv(inBufSize)exceptException:

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)defp2psend(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)exceptException,e:printe

remote_socket.close()

CONNECTION_LIST.remove(remote_socket)defbroadcast(self,local_id,message):for sock inCONNECTION_LIST:if sock ==self.serverSocket:continue

else:try:

message_send= "%s said : %s" %(local_id, message)

sock.send(message_send)exceptException,e:printe

sock.close()

CONNECTION_LIST.remove(sock)continue

defsocet_handle(self):while 1:#Get the list sockets which are ready to be read through select

read_sockets, write_sockets, error_sockets =select.select(CONNECTION_LIST, [], [])for sock inread_sockets:#New connection

if sock == self.serverSocket:#用户通过主socket(即服务器开始创建的 socket,一直处于监听状态)来登录

#Handle the case in which there is a new connection recieved through server_socket

sockfd, addr =self.serverSocket.accept()

id= sockfd.recv(100)

self.login(id,sockfd)else:

self.chat(sock)defmain(self):

self.socet_handle()

self.serverSocket.close()if __name__ == '__main__':

chat_server_obj=ChatServer()

chat_server_obj.main()

三、客户端程序

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

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

defsocket_handler(self):while 1:

rlist= [sys.stdin, self.client_socket] #接收列表

read_list, write_list, error_list = select.select(rlist, [], [], 2)for sock inread_list:#incoming message from remote server

if sock ==self.client_socket:

data= sock.recv(4096)if notdata:print '\nDisconnected from chat server'sys.exit()else:#print data

sys.stdout.write(data)

self.prompt()#user entered a message

else:

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 -*-

importsocket, select, string, sys

HOST= '127.0.0.1'PORT= 5247ID= '1'

classChatClient:def __init__(self):

self.client_socket=socket.socket(socket.AF_INET, socket.SOCK_STREAM)

self.client_socket.settimeout(2)

self.connect()defconnect(self):try:

self.client_socket.connect((HOST, PORT))

self.client_socket.send(ID)exceptException,e:print 'Unable to connect because of %s'%e

sys.exit()else:print 'Connected to remote host. Start sending messages'self.prompt()defprompt(self):

sys.stdout.write('\n')

sys.stdout.flush()defsocket_handler(self):while 1:

rlist= [sys.stdin, self.client_socket] #接收列表

read_list, write_list, error_list = select.select(rlist, [], [], 2)for sock inread_list:#incoming message from remote server

if sock ==self.client_socket:

data= sock.recv(4096)if notdata:print '\nDisconnected from chat server'sys.exit()else:#print data

sys.stdout.write(data)

self.prompt()#user entered a message

else:

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实现简易聊天需要登录_python socket编程 实现简单p2p聊天程序相关推荐

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

    转载自:https://www.cnblogs.com/wuxie1989/p/7204887.html python socket编程 实现简单p2p聊天程序 目标是写一个python的p2p聊天的 ...

  2. python webdriver 等待网页已登录_python基础编程:python+selenium实现163邮箱自动登陆的方法...

    本文介绍了 让我们先来预览一下代码运行效果吧: 首先分析163邮箱登陆页面的网页结构(按F12或单击鼠标右键选择审查元素) 1.定位到登陆框(注意登录框是一个iframe,如果不定位到iframe的话 ...

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

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

  4. java socket通信 客户端_JavaのSocket编程之简单客户端与服务器端通信

    Socket编程之简单客户端与服务器端通信 socket 通常用来实现客户端和服务端的连接,socket 是Tcp/Ip协议的一个十分流行的编程界面,一个socket 由一个Ip地址和一个端口号唯一确 ...

  5. Socket编程之简单介绍 - 蓝天下的雨 - 博客园

    Socket编程之简单介绍 - 蓝天下的雨 - 博客园 Socket编程之简单介绍 - 蓝天下的雨 - 博客园 Socket编程之简单介绍 2013-03-19 15:27 by 蓝天下的雨, 878 ...

  6. python socket多线程 获取朋友列表_python socket多线程通讯实例分析(聊天室)

    本文实例讲述了python socket多线程通讯方法.分享给大家供大家参考,具体如下: #!/usr/bin/evn python """ 这是一个Socket+多进程 ...

  7. 用python画分时图_Python socket编程之四:模拟分时图

    建立 socket,先运行服务器,再运行客户端,建立连接后服务器从本地数据库调数据一截一截地发送给客户端,客户端接受数据绘图模拟分时图 1.socket # -*- coding: utf-8 -*- ...

  8. python的socket编程_Python Socket编程详细介绍

    在使用Python做socket编程时,由于需要使用阻塞(默认)的方式来读取数据流,此时对于数据的结束每次都需要自己处理,太麻烦.并且网上也没找到太好的封装,所以就自己写了个简单的封装. 封装思路 1 ...

  9. python send 案例_python socket编程入门(编写server实例)+send 与sendall的区别与使用方法...

    python 编写server的步骤: 1. 第一步是创建socket对象.调用socket构造函数.如: socket = socket.socket( family, type ) family参 ...

最新文章

  1. Winform DataGridView列的单元格中动态添加图片和文字
  2. android画笔画图(会持续更新完善,欢迎留言提问)
  3. getpass 模块
  4. 45页的NAS神经网络搜索的综述,请查收!
  5. centos 6.9 NTP基准时间服务器配置
  6. C++ 控制结构和函数(三)—— 函数II(Functions II)
  7. 【转】超酷的 mip-infinitescroll 无限滚动(无限下拉)
  8. 2.Java 面试题整理(基础篇二)
  9. caffe linux跑自己数据,caffe+linux平台——跑深度学习的流程
  10. lnmp python _mysql web_Nginx+uWSGI+DJango+Python+ Mysql 搭建可靠的python web服务器
  11. vue-router如何参数传递
  12. 常用的python内置方法
  13. 未来-IOT-Aliyun:阿里云 IOT - 开发者社区
  14. java多网卡组播,多网卡 组播
  15. 测试开发面试-技术题持续累积
  16. mysql 名字分组查询id_MySQL对数据表进行分组查询(GROUP BY)
  17. Mac OS X 上用 otool 代替 ldd
  18. 星光不问赶路人,时光不负奇舞团
  19. Java 多线程 生产者和消费者
  20. Taylor Swift - Mean-pdf

热门文章

  1. 导入MVVMLight出现错误 ViewModelLocator does not exist in the namespace clr-namespace:WpfApp1.ViewModel
  2. 1.1 Java HTML前端网页
  3. MCK主机加固数据安全解决方案
  4. Unity简单使用Job System
  5. xxl-job学习,基本测试1
  6. 5V升压8.4V的2A充电电路芯片-PW4202
  7. AT89C52RC定时器T2
  8. 在创建jsp页面之后保存时提示错误,并提示以UTF-8格式进行保存。
  9. 如果阿里裁员30%是真的,你拿什么和阿里背景的程序员竞争?
  10. 两点定标法_生化分析仪的定标方法