python网络编程
| 协议 | 功能用处 | 端口号 | Python 模块 | | HTTP | 网页访问 | 80 | httplib, urllib(request), xmlrpclib | | NNTP | 阅读和张贴新闻文章,俗称为"帖子" | 119 | nntplib | | FTP | 文件传输 | 20 | ftplib, urllib | | SMTP | 发送邮件 | 25 | smtplib | | POP3 | 接收邮件 | 110 | poplib | | IMAP4 | 获取邮件 | 143 | imaplib | | Telnet | 命令行 | 23 | telnetlib | | Gopher | 信息查找 | 70 | gopherlib, urllib |
什么是 socket?简述基于 tcp 协议的套接字通信流程。
socket(简称套接字) 是进程间通信的⼀种⽅式, 能实现不同主机间的进程间通信。
流程:
通信双方实例化tcpSocket对象,服务端绑定ip和端口号并执行lisient()方法进入监听状态。
客户端执行connect()方法请求连接,双方完成三次握手建立连接(模块内部实现)。
服务段执行accept()方法获得连接对象,双方实现通信。
通信结束执行close()方法关闭连接。
简述基于 udp 协议的套接字通信流程。
通信双方实例化tcpSocket对象,服务端绑定ip和端口号。
客户端和服务端都可以执行sendto()方法发送数据给指定ip地址和端口号的主机。
客户端和服务端都可以执行recvfrom()方法获得发送给自己的数据以及发送方的ip和端口号。
通信结束执行close()关闭socket对象。
网络编程中设计并发服务器,使用多进程与多线程,请问有什么区别?
多进程:
开启多个进程为客户端服务,同一时刻可为多个客户端提供服务,但是任务量大会因为创建进程的开销影响服务器性能。
多线程:
一个进程内开启多个线程,同一时刻只能为一个客户端服务,I/O等待的时间可以进行别的任务,不会浪费时间,不影响服务器性能,推荐使用。
大规模连接上来,并发模型怎么设计?
多进程:
开启多个进程为客户端服务,同一时刻可为多个客户端提供服务,但是任务量大会因为创建进程的开销影响服务器性能。
多线程:
一个进程内开启多个线程,同一时刻只能为一个客户端服务,I/O等待的时间可以进行别的任务,不会浪费时间,不影响服务器性能,推荐使用。
协程:
协程的优势在于函数入口可以是上次停止的地方,显然对大规模连接没什么帮助。
所以这种情况推荐使用多线程来设计并发模式。
基于TCP协议的socket
tcp是基于链接的,必须先启动服务端,然后再启动客户端去链接服务端
server端
import socket sk = socket.socket() sk.bind(('127.0.0.1',8898)) #把地址绑定到套接字 sk.listen() #监听链接 conn,addr = sk.accept() #接受客户端链接 ret = conn.recv(1024) #接收客户端信息 print(ret) #打印客户端信息 conn.send(b'hi') #向客户端发送信息 conn.close() #关闭客户端套接字 sk.close() #关闭服务器套接字(可选)
client端
import socket sk = socket.socket() # 创建客户套接字 sk.connect(('127.0.0.1',8898)) # 尝试连接服务器 sk.send(b'hello!') ret = sk.recv(1024) # 对话(发送/接收) print(ret) sk.close() # 关闭客户套接字
完整tcp
from socket import socket sk = socket(type=socket.SOCK_STREAM) sk.bind(('127.0.0.1',9090)) sk.listen() while 1: # print(123) conn,addr = sk.accept() # 等待连接 -- 阻塞 # print(456) while 1: # print(789) msg_r = conn.recv(1024).decode('utf-8') # 阻塞等待接收客户端发来的消息 # print('jqk') print('接收到来自%s的一个消息:%s' % (addr, msg_r)) if msg_r == 'q': break msg_s = input('>>>') conn.send(msg_s.encode('utf-8'))# 发送给客户端消息 if msg_s == 'q': break conn.close()# 服务器和当前客户端断开连接,程序回到上一层死循环,重新等待客户端的连接 sk.close() from socket import socket sk = socket() sk.connect(('127.0.0.1',9090)) while 1: msg_s = input('>>>') sk.send(msg_s.encode('utf-8')) if msg_s == 'q': break msg_r = sk.recv(1024).decode('utf-8') print(msg_r) if msg_r == 'q': break sk.close()
udp
import socket sk = socket.socket(type=socket.SOCK_DGRAM)# udp协议 sk.bind(('127.0.0.1',9090)) dic = {'alex':'\033[0;33;42m','太白':'\033[0;35;40m'} while 1: msg_r,addr = sk.recvfrom(1024)# 接收来自哪里的消息 msg_r = msg_r.decode('utf-8')# alex : 我要退学 # 对于msg_r,通过':'分割,获取下标为0的,也就是name,再去掉name的左右两边的空格 name = msg_r.split(':')[0].strip() color = dic.get(name,'')# 获取字典中 name所对应的 颜色值 print('%s%s \033[0m'%(color,msg_r)) if msg_r == 'q':# 如果当前客户端想要断开连接 continue # 服务器端不应该继续通话了,应该等待接收另一个客户端的连接,返回到recvfrom msg_s = input('>>>') sk.sendto(msg_s.encode('utf-8'), addr) if msg_s == 'q': break sk.close() import socket sk = socket.socket(type=socket.SOCK_DGRAM) name = input('请输入您的名字:>>>') while 1: msg_s = input('>>>') msg_s = name + " : "+msg_s sk.sendto(msg_s.encode('utf-8'),('127.0.0.1',9090))# 发给谁一条消息 if msg_s is 'q': break msg_r,addr = sk.recvfrom(1024) msg_r = msg_r.decode('utf-8') print(msg_r) if msg_r == 'q': break sk.close()
udp时间同步
import socket import time sk = socket.socket(type=socket.SOCK_DGRAM) sk.bind(('127.0.0.1',9090)) while 1: tm_format,addr = sk.recvfrom(1024) tm_format = tm_format.decode('utf-8')# %Y-%m\%d %H:%M:%S local_tm = time.strftime(tm_format)# 获取到了对应格式的当前时间 sk.sendto(local_tm.encode('utf-8'),addr)# 返回给客户端 sk.close() import socket import time sk = socket.socket(type=socket.SOCK_DGRAM) tm_format = input('>>>') while 1: sk.sendto(tm_format.encode('utf-8'),('127.0.0.1',9090)) local_tm,addr = sk.recvfrom(1024) print(local_tm.decode('utf-8')) time.sleep(2)
https://blog.csdn.net/xuzhexing/article/details/90763756
作为客服端与HTTP服务交互
1.1 简单HTTP请求
发送一个简单HTTP GET请求到远程的服务
from urllib import request,parse # base url being accessed url='http://httpin.org/get' #dictionary of qurey parameters parms={ 'name1':'value1', 'name2':'value2' } #encode the query string querystring=parse.urlencode(params) # make a get request and read the response u=request.urlopen(url+'?'+querystring) resp=u.read()
需要使用POST方法请求主体中发送查询参数,尅讲参数编码后变为可选参数提供给urlopen()函数
from urllib import request,parse #base URL being accessed url="http://httpbi.org/post" #dictionary of query parameters(of any) parms={ 'name1':'value1', 'name2':'value2' } # extra headers headers={ 'User-agent':'none/ofyourbusiness', 'Spam':'Eggs' } #encode the query string querystring=parse.urlencode(parms) # make a POST request and read the response u=request.urlopen(url,querystirng.encode('ascii'),headers=headers) resp=u.read()
1.2服务器交互
采用requests库来实现。
import requests # base url being accessed url='http://httpbin.org/post' #dictionary of qurey parmeters (if any) parms={ 'name1':'value', 'name2':'value2' } # extra headers headers={ 'User-agent':'none/ofyourbusiness', 'Spam':'Eggs' } resp=requests.post(url,data=parms,headers=headers) # decode text returned by the request text=resp.text #Unicode解码的响应文本 content=resp.content # 得到二进制数据 json=resp.json # 得到JSON格式数据
requests库发起一个HEAD请求,从响应中提取一些HTTP头数据的字段:
resp=request.head('http://www.python.org/index.html') status=resp.status_code last_modified=resp.headers['last-modified'] content_type=resp.headers['content-type'] content_length=resp.headers['content-length']
利用requests通过基本认证登录Pypi的例子
resp=request.get('http://pypi.python.org/pypi?:action=login',auth=(‘user’,'passwd'))
利用requests将HTTP cookies从一个请求传递到另一个例子:
import requests #first request resp1=requests.get(url) ... # second requests with cookies received on first requests resp2=requests.get(url,cookies=respq.cookies)
最后requests上传内容:
import requests ur='http://httpin.org/post' files={'file':('data.csv',open('data.csv'),'rb')} r=requests.post(url,files=files)

浙公网安备 33010602011771号