python编程16章_Python核心编程——Chapter16
好吧,在拜读完《Python网络编程基础》之后,回头再搞一搞16章的网络编程吧。
Let‘s go!
16.4.修改书上示例的TCP和UDP客户端,使得服务器的名字不要在代码里写死,要允许用户指定一个主机名和端口。只有两个值都没有输入是才使用默认值。
难度不大。
#tsTclnt.py#!/usr/bin/env python#-*-coding:utf-8-*-
from socket import *
importsysif(len(sys.argv) < 3):
HOST= 'localhost'PORT= 21567
else:
HOST= sys.argv[1]
PORT= int(sys.argv[2])
BUFSIZ= 1024ADDR=(HOST,PORT)
tcpCliSock=socket(AF_INET,SOCK_STREAM)
tcpCliSock.connect(ADDR)whileTrue:
data= raw_input('>')if notdata:breaktcpCliSock.send(data)
data=tcpCliSock.recv(BUFSIZ)if notdata:break
printdata
tcpCliSock.close()
#tsUclnt.py#!/usr/bin/env python#-*- coding:utf-8 -*-
from socket import *
importsysif(len(sys.argv) < 3):
HOST= 'localhost'PORT= 21567
else:
HOST= sys.argv[1]
PORT= sys.argv[2]#print sys.argv[1],sys.argv[2]
BUFSIZ= 1024ADDR=(HOST,int(PORT))
udpCliSock=socket(AF_INET,SOCK_DGRAM)whileTrue:
data= raw_input('>')if notdata:breakudpCliSock.sendto(data,ADDR)
data,ADDR=udpCliSock.recvfrom(BUFSIZ)if notdata:break
printdata
udpCliSock.close()
16.5.修改服务器示例代码,使得它能根据不同的请求而作出应答。
这道题目本质上也不难,只需要在服务器的死循环程序加上条件判断即可。
版本1:纯TCP服务器端修改。
#!/usr/bin/env python#-*- coding:utf-8 -*-
from socket import *
importtime,os
HOST= ''PORT= 21567BUFSIZ= 1024ADDR=(HOST,PORT)
tcpSerSock=socket(AF_INET,SOCK_STREAM)
tcpSerSock.bind(ADDR)
tcpSerSock.listen(5)whileTrue:print 'waiting for connection...'tcpCliSock,addr=tcpSerSock.accept()print '...connected from:',addrwhileTrue:
data=tcpCliSock.recv(BUFSIZ)
data=data.strip()if notdata:break
if data == "date":
tcpCliSock.send('%s' %(time.ctime(time.time())))elif data == "os":
tcpCliSock.send('%s' %(os.name))elif data == "ls":
tcpCliSock.send('%s' %(os.listdir(os.curdir)))else:
tcpCliSock.send('[%s] %s' %(ctime(),data))
tcpCliSock.close()
tcpSerSock.close()
版本2:使用现成的服务器框架进行修改。
#!/usr/bin/env python#-*-coding:utf-8-*-
from SocketServer importThreadingMixIn,TCPServer,StreamRequestHandlerimporttime,os,reclassTxRequestHandler(StreamRequestHandler):defhandle(self):
req=self.rfile.readline().strip()
m= re.match('(\w+)\s+([\w+/]+)',req)if req == "date":
result=time.ctime(time.time())elif req == "os":
result=os.nameelif req == "ls":
result=str(os.listdir(os.curdir))elif m is not None and m.lastindex == 2 and m.group(1) == 'ls':
result= str(os.listdir(m.group(2)))else:
result= """date -- 服务器将返回它的当前时间
os -- 得到操作系统的信息
ls -- 得到当前目录的文件列表"""self.wfile.write(result+"\n")classTxServer(ThreadingMixIn,TCPServer):
allow_reuse_address= 1serveraddr= ('',8765)
srvr=TxServer(serveraddr,TxRequestHandler)
srvr.serve_forever()
16.7.实现一个半双工的聊天方式,其中一个人是服务端,另一个人是客户端。
其实也不难,只是将回射服务器做部分修改就可以。
服务器端:
#!/usr/bin/env python#-*- coding:utf-8 -*-
from socket import *
from time importctime
HOST= ''PORT= 21567BUFSIZ= 1024ADDR=(HOST,PORT)
tcpSerSock=socket(AF_INET,SOCK_STREAM)
tcpSerSock.bind(ADDR)
tcpSerSock.listen(5)whileTrue:print 'waiting for connection...'tcpCliSock,addr=tcpSerSock.accept()print '...connected from:',addrwhileTrue:
rdata=tcpCliSock.recv(BUFSIZ)if notrdata:break
printrdata
sdata= raw_input(">")
tcpCliSock.send('[%s] %s' %(ctime(),sdata))
tcpCliSock.close()
tcpSerSock.close()
客户端:
#!/usr/bin/env python#-*-coding:utf-8-*-
from socket import *
importsysif(len(sys.argv) < 3):
HOST= 'localhost'PORT= 21567
else:
HOST= sys.argv[1]
PORT= int(sys.argv[2])
BUFSIZ= 1024ADDR=(HOST,PORT)
tcpCliSock=socket(AF_INET,SOCK_STREAM)
tcpCliSock.connect(ADDR)whileTrue:
data= raw_input('>')if notdata:breaktcpCliSock.send(data)
data=tcpCliSock.recv(BUFSIZ)if notdata:break
printdata
tcpCliSock.close()
16.8.实现一个全双工的聊天方式,即两个人可以独立地发送和接收消息。
全双工其实原理也不太难,但是我一直傻逼了,一直用写服务器端的方法去实现客户端的程序。
我所使用的方法也是最常用的技术——多线程。以下是服务器端和客户端的编写思路:
服务器端:在服务器端我主要用了一个主线程来accept客户端的链接,没接受了一个连接,就新建两个线程,一个用于发送消息,一个用于接收消息。
客户端:思路完全不一样,由于客户端面对的只有服务器,所以主线程只能是接收消息(发送消息),然后发送消息(接收消息)作为一个线程来并发。
由于这里的数据并不是共享的,所以这里的线程写起来就很轻松,不用考虑同步问题。
服务器端:
#!/usr/bin/env python#-*- coding:utf-8 -*-
importsocket,traceback,osfrom threading import *host= ''port= 51423 #监听所有的接口
#接受消息的线程
defhandlerecv(clientsock):print "New child",currentThread().getName()print "Got connection from",clientsock.getpeername()whileTrue:
data= clientsock.recv(4096)if notlen(data):break
printdata
clientsock.close()#发送消息的线程
defhandlesend(clientsock):whileTrue:
data= raw_input(">")
data= data + "\n"; #加上换行,好看一点。
clientsock.sendall(data)#关闭连接
clientsock.close()#建立套接字
s =socket.socket(socket.AF_INET,socket.SOCK_STREAM)
s.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
s.bind((host,port))
s.listen(1)whileTrue:try:
clientsock,clientaddr=s.accept()exceptKeyboardInterrupt:raise
except:
traceback.print_exc()continuet= Thread(target = handlerecv,args=[clientsock])
t.setDaemon(1)
t.start()
r= Thread(target = handlesend,args=[clientsock])
r.setDaemon(1)
r.start()
客户端:
#!/usr/bin/env python#-*-coding:utf-8-*-
from socket import *
importsysfrom threading import *
if(len(sys.argv) < 3):
HOST= 'localhost'PORT= 51423
else:
HOST= sys.argv[1]
PORT= int(sys.argv[2])
BUFSIZ= 1024ADDR=(HOST,PORT)defhandlesend(tcpCliSock):whileTrue:
sdata= raw_input('>')if notsdata:breaktcpCliSock.send(sdata)
tcpCliSock.close()
tcpCliSock=socket(AF_INET,SOCK_STREAM)
tcpCliSock.connect(ADDR)#建立发送消息的线程
s = Thread(target = handlesend,args=[tcpCliSock])
s.setDaemon(1)
s.start()whileTrue:
rdata=tcpCliSock.recv(BUFSIZ)if notrdata:break
printrdata
tcpCliSock.close()
16.10.实现一个多房间全双工的聊天方式,把聊天服务器改成支持多用户版本。
其实思路差不多,只不过过程有点繁琐,在服务器端要建立字典,作为房间,然后每个套接字存在字典当中,然后作适当的分发。
另外一种方法使用广播不知道可不可以了。
这里直接贴人家写的代码学习一下:
服务器端:
#!/usr/bin/env python#_*_ coding: utf8 _*_
from socket import *
from time importctimeimportthreadingfrom string importsplit
HOST= ''PORT= 21567BUFSIZE= 1024ADDR=(HOST, PORT)defDeal(sck, username, room):whileTrue:
data=sck.recv(BUFSIZE)for i inclients[room].iterkeys():if i <>username:if data <> "quit":
clients[room][i].send("[%s] %s: %s" %(ctime(), username, data))else:
clients[room][i].send("用户%s在%s退出房间%s" %(username, ctime(), room ))if data == "quit":delclients[room][username]
sck.send(data)
sck.close()breakchatSerSock=socket(AF_INET, SOCK_STREAM)
chatSerSock.bind(ADDR)
chatSerSock.listen(5)
clients= {"":{},}whileTrue:print 'waiting for connection...'chatCliSock, addr=chatSerSock.accept()print "...connected romt:", addr
data=chatCliSock.recv(BUFSIZE)
username, room=split(data)printusernameif notclients.has_key(room):
clients[room]={}ifclients[room].has_key(username):
chatCliSock.send("reuse")
chatCliSock.close()else:
chatCliSock.send("success")
clients[room][username]=chatCliSock
t= threading.Thread(target=Deal, args=(chatCliSock, username, room))
t.start()
chatSerSock.close()
客户端:
#!/usr/bin/env python#_*_ coding: utf8 _*_
from socket import *
from time importctimeimportthreadingimportrandomfrom sys importargv, exit, stdoutfrom getopt importgnu_getopt, GetoptError
help_info= ["cs.py [ -h | --help | -u | --username] username","\t-h or --help\t显示帮助信息","\t-u or --username\指定用户名","\t-r or --room\t指定房间"]defhelp():for i inhelp_info:printidefSend(sck, test):whileTrue:
data= raw_input('>')
sck.send(data)if data == "quit":break
defRecieve(sck, test):whileTrue:
data=sck.recv(BUFSIZ)if data == "quit":
sck.close()breakstr= "\n" + data + "\n>"stdout.write(str)
HOST= 'localhost'PORT= 21567BUFSIZ= 1024ADDR=(HOST, PORT)
threads=[]if __name__ == "__main__":#解析命令行参数
try:
opts, args= gnu_getopt(argv[1:], "hu:r:", ["help", "username=", "room="])exceptGetoptError, err:printstr(err)
help()
exit(2)
username= ""room= ""
for o, a inopts:if o in ("-h", "--help"):
help()
exit(0)elif o in ("-u", "--username"):
username=aelif o in ("-r", "--room"):
room=aelse:print "未知选项"help()
exit(2)if not username or notroom:
help()
exit(2)
chatCliSock=socket(AF_INET, SOCK_STREAM)
chatCliSock.connect(ADDR)
chatCliSock.send("%s %s" %(username, room))
data=chatCliSock.recv(BUFSIZ)if data == "reuse":print "用户%s已登录房间%s" %(username, room)
raw_input()
exit(1)elif data == "success":print "用户%s成功登录房间%s" %(username, room)
t= threading.Thread(target=Send, args =(chatCliSock, None))
threads.append(t)
t= threading.Thread(target=Recieve, args =(chatCliSock, None))
threads.append(t)for i inrange(len(threads)):
threads[i].start()
threads[0].join()
16.11.写一个网页客户端。自己新建一个套接字,然后发送http请求。
感觉难度不大。
#!/usr/bin/env python#-*-coding:utf-8-*-
importsocket,sys
website= sys.argv[1]
port= 80
printwebsiteprint "Creating socket...",
s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)print "done."
print "Connecting to ...",
s.connect((website,port))print "done."s.send("GET /index.html HTTP/1.0\r\n\r\n")
data= s.recv(4096)print data
16-12.休眠服务器,在服务器端上面加个sleep(num)就好,在这里就不贴了。
16-13.功能太过复杂,本人渣渣,没精力写。
16-14.考虑的东西很多,水平有限,不做了。
16-15.异步和SocketServer。这个用多线程可以实现,在《python网络编程基础》上面直接有源码。使用方法都有教。
#!/usr/bin/env python#-*- coding:utf-8 -*-
from SocketServer importThreadingMixIn,TCPServer,StreamRequestHandlerimporttimeclassTimeRequestHandler(StreamRequestHandler):defhandle(self):
req=self.rfile.readline().strip()if req == "asctime":
result=time.asctime()elif req == "seconds":
result=str(int(time.time()))elif req == "rfc822":
result= time.strftime("%a, %d %b %Y %H:%M:%S +0000",time.gmtime())else:
result= """Unhandled request.Send a line with one of the following words:
asctime -- for human-readable time
seconds -- seconds since the Unix Epoch
rfc822 -- data/time in format used for mail and news posts"""self.wfile.write(result+ "\n")classTimeServer(ThreadingMixIn,TCPServer):
allow_reuse_address= 1serveraddr= ('',8765)
srvr=TimeServer(serveraddr,TimeRequestHandler)
srvr.serve_forever()
多多指教!谢谢!
python编程16章_Python核心编程——Chapter16相关推荐
- python编程15章_python核心编程2 第十五章 练习
15-1.识别下列字符串 :"bat "."bit "."but "."hat "."hit" 或 ...
- python课后题答案第一章_python核心编程课后习题解答第一章
闲着没事,决定将<python核心编程>这本书的课后习题做一遍,以增加自己的编程能力. 1-1 将python安装到系统上 本人用的ubuntu系统,系统中自带了python,无需安装,本 ...
- python程序练习题第三章_python核心编程-第三章-习题
1.这是python的语言特性,python先创建对象,在给变量赋值时,不需要定义变量的名称和类型,它实际是用变量引用对象.变量类型在给变量赋值时自动声明 2.原因类似变量无须声明类型 3.pytho ...
- python教材答案第四章_python核心编程课后习题解答第四章
4–1. Python 对象.与所有Python 对象有关的三个属性是什么?请简单的描述一下. type.ID.value..(身份.类型.值) type()接受一个对象作为参数,并返回它的类型 id ...
- python第五章课后编程题答案_Python核心编程-第五章课后习题
5-1 整形 讲讲 Python 普通整型和长整型的区别 答:在2.7版本基本淡化了区别.真要区分的话,普通整型是32位或者64位,而长整型只与PC内存有关,很大就是了 5-2 运算符 (a) 写一个 ...
- python核心编程怎么做_Python核心编程:8个实践性建议
前言 我们在用Python进行机器学习建模项目的时候,每个人都会有自己的一套项目文件管理的习惯,我自己也有一套方法,是自己曾经踩过的坑踩过的雷总结出来的,现在在这里分享一下给大家,因为很多伙伴是接触P ...
- python语句行从解释器提示符后第几列开始_Python核心编程(第2版)PDF文档免费下载...
第1部分 Python核心 第1章 欢迎来到Python世界 1.1 什么是Python 1.2 起源 1.3 特点 1.3.1 高级 1.3.2 面向对象 1.3.3 可升级 1.3.4 可扩展 1 ...
- python归一化 增大差异_简学Python第六章__class面向对象编程与异常处理
Python第六章__class面向对象编程与异常处理 欢迎加入Linux_Python学习群 群号:478616847 目录: 面向对象的程序设计 类和对象 封装 继承与派生 多态与多态性 特性pr ...
- 从零学python黑马程序员_Python实战编程--从零学Python/Python应用编程丛书
导语 内容提要 黑马程序员编著的<Python实战编程--从零学Python>涵盖了Python开发的核心知识.其中,第1-13章主要讲解的是Python的核心语法,包括基本概念和语句.风 ...
最新文章
- python3 字符串、十六进制字符串、数字、字节之间的转换
- bilibili怎么设置弹幕数量_python爬虫:bilibili弹幕爬取+词云生成
- python学习教程,猜数字游戏开发
- 利用STL离散化处理数据(unique)
- idea搭建可运行Servlet的Web项目[maven]
- 通过IDE生成和手动call调用webservice
- 在web项目中集成xfire的方法
- CVX 几何规划 两个官网样例
- Extjs, each中实现break、continue
- iOS App创建桌面快捷方式
- Fedora17下Firefox安装flashplayer
- jpa双向一对一关联外键映射
- 运行Arcgis和SWAT模型遇到Error Number 91和Error Number -2147467259报错怎么办?
- 如何规划自己的人生未来
- 数据泵并行parallel参数问题
- pl/sql Developer 1303注册码
- Zookeeper 客户端之 Curator
- 计算机硬件系统一直延用,会计电算化计算机硬件系统
- 个人电脑厂商艰难涉水家庭娱乐市场
- 说说wps jsa的ListBox控件的数组写入方法
热门文章
- python 库整理:Timm(1)
- Flink从入门到精通100篇(二十三)-基于Apache Flink的爱奇艺实时计算平台建设实践
- matlab实战系列之人工鱼群算法求解TSP问题原理解析(下篇源码解析)
- python网络爬虫爬取房价信息
- 【云计算】6_云数据库产品介绍
- Python编程基础:第五十九节 守护线程Daemon Threading
- JVM 生态系统 2018 调查报道
- 兼顾稳定和性能,58大数据平台的技术演进与实践
- 用最少的机器支撑万亿级访问,微博6年Redis优化历程
- 对request.getSession(false)的理解(附程序员常疏忽的一个漏洞)--转