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)

 

posted @ 2021-08-15 14:25  holmes_now  阅读(43)  评论(0)    收藏  举报