python学习笔记11 ----网络编程

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了python学习笔记11 ----网络编程相关的知识,希望对你有一定的参考价值。

网络编程

网络编程需要知道的概念 

1.网络体系结构就是使用这些用不同媒介连接起来的不同设备和网络系统在不同的应用环境下实现互操作性,并满足各种业务需求的一种粘合剂。网络体系结构解决互质性问题彩是分层方法。

网络(OSI)的7层模型:

应用层--->为应用程序提供网络通信服务

表示层--->数据表示

会话层--->主机间通信(两个应用进程间)

传输层--->端到端的连接,隔离网络的上下层协议,使得网络应用与下层协议无关

网络层--->寻找最优路径,转发数据包

数据链路层--->无差错的链路连接

物理层--->二进制传输

技术分享技术分享

2.端口

  是一种抽象的软件结构,包括一些数据结构和I/O缓冲区。与协议有关。

3.套接字存在于通信区域中。通信区域也叫地址族,它是一个抽象的概念,主要用于将通过套接字通信的进程的共有特性综合在一起。

为保证数据的正确性,在网络协议中需要制定网络字节顺序,采用统一的网络字节顺序。

网络通信三要素:

  IP地址:用于表示主机(IP地址 = 网络ID+主机ID)

  端口号:用于标识进程的逻辑端口

  传输协议:TCP UDP

网络通信过程就是一个不断封装和解析的过程

Socket是连接应用程序与网络驱动程序的桥梁,Socket在应用程序中创建,通过绑定操作与驱动程序建立关系。

套接字

  套接字是为特定网络协议(例如TCP/IP,ICMP/IP,UDP/IP等)套件对上的网络应用程序提供者提供当前可移植标准的对象。它们允许程序接受并进行连接,如发送和接受数据。为了建立通信通道,网络通信的每个端点拥有一个套接字对象极为重要。

套接字为BSD UNIX系统核心的一部分,而且他们也被许多其他类似UNIX的操作系统包括Linux所采纳。许多非BSD UNIX系统(如ms-dos,windows,os/2,mac os及大部分主机环境)都以库形式提供对套接字的支持。

三种最流行的套接字类型是:stream,datagram和raw。stream和datagram套接字可以直接与TCP协议进行接口,而raw套接字则接口到IP协议。但套接字并不限于TCP/IP。

套接字模块 -------SOCKET()模块

  套接字模块是一个非常简单的基于对象的接口,它提供对低层BSD套接字样式网络的访问。使用该模块可以实现客户机和服务器套接字。要在python 中建立具有TCP和流套接字的简单服务器,需要使用socket模块。利用该模块包含的函数和类定义,可生成通过网络通信的程序。要在python 中建立具有TCP和流套接字的简单服务器,需要使用socket模块。利用该模块包含的函数和类定义,可生成通过网络通信的程序。 

   

soc                           

SOCKET内建方法

函数  描述
服务器端套接字函数  
s.bind()   绑定地址(主机,端口号对)到套接字
s.listen() 开始TCP 监听
s.accept()   被动接受TCP 客户的连接,(阻塞式)等待连接的到来
客户端套接字函数  
s.connect() 主动初始化TCP 服务器连接
s.connect_ex() connect()函数的扩展版本,出错时返回出错码,而不是抛异常
公共用途的套接字函数  
s.recv() 接收TCP 数据
s.send() 发送TCP 数据
s.sendall() 完整发送TCP 数据
s.recvfrom() 接收UDP 数据
s.sendto() 发送UDP 数据
s.getpeername()     连接到当前套接字的远端的地址
s.getsockname() 当前套接字的地址
s.getsockopt()     返回指定套接字的参数
s.setsockopt()     设置指定套接字的参数
s.close() 关闭套接字
面向模块的套接字函数  
s.setblocking()  设置套接字的阻塞与非阻塞模式
s.settimeout()a 设置阻塞套接字操作的超时时间
s.gettimeout()a 得到阻塞套接字操作的超时时间
面向文件的套接字的函数  
s.fileno() 套接字的文件描述符
s.makefile()     创建一个与该套接字关连的文件
a. Python 2.3 版本新加入的函数  

建立服务器连接需要六个步骤:

  1.创建socket对象。调用socket构造函数。

  socket=socket.socket(familly,type)

  family的值可以是AF_UNIX(Unix域,用于同一台机器上的进程间通讯),也可以是AF_INET(对于IPV4协议的TCP和 UDP),至于type参数,SOCK_STREAM(流套接字)或者 SOCK_DGRAM(数据报文套接字),SOCK_RAW(raw套接字)。

  2.则是将socket绑定(指派)到指定地址上,socket.bind(address)

  address必须是一个双元素元组,((host,port)),主机名或者ip地址+端口号。如果端口号正在被使用或者保留,或者主机名或ip地址错误,则引发socke.error异常。

  3.绑定后,必须准备好套接字,以便接受连接请求。

  socket.listen(backlog)

backlog指定了最多连接数,至少为1,接到连接请求后,这些请求必须排队,如果队列已满,则拒绝请求。

  4.服务器套接字通过socket的accept方法等待客户请求一个连接:

  connection,address=socket.accept()

调用accept方法时,socket会进入‘waiting‘(或阻塞)状态。客户请求连接时,方法建立连接并返回服务器。accept方法返回 一个含有俩个元素的元组,形如(connection,address)。第一个元素(connection)是新的socket对象,服务器通过它与客 户通信;第二个元素(address)是客户的internet地址。

  5.  处理阶段,服务器和客户通过send和recv方法通信(传输数据)。服务器调用send,并采用字符串形式向客户发送信息。send方法 返回已发送的字符个数。服务器使用recv方法从客户接受信息。调用recv时,必须指定一个整数来控制本次调用所接受的最大数据量。recv方法在接受 数据时会进入‘blocket‘状态,最后返回一个字符串,用它来表示收到的数据。如果发送的量超过recv所允许,数据会被截断。多余的数据将缓冲于接 受端。以后调用recv时,多余的数据会从缓冲区删除。

  6. 传输结束,服务器调用socket的close方法以关闭连接。

建立一个简单客户连接则需要4个步骤。

第1步,创建一个socket以连接服务器 socket=socket.socket(family,type)

第2步,使用socket的connect方法连接服务器 socket.connect((host,port))

第3步,客户和服务器通过send和recv方法通信。

第4步,结束后,客户通过调用socket的close方法来关闭连接。

技术分享

技术分享
import socket
sk = socket.socket()
address = (127.0.0.1,8000)
sk.bind(address)     
sk.listen(2)
print("......")
while True:
    conn, addr = sk.accept()
    print(addr)
    while True:
        try:
            date = conn.recv(1024)
        except Exception:
            break
        if not date:break
        print(str(date, "utf8"))
        inp = input(">>>>:")
        conn.send(bytes(inp,"utf8"))
# conn, addr = sk.accept()
# while True:
#     date = conn.recv(1024)
#     if not date:
#         conn, addr = sk.accept()
#         continue
#     print(str(date, "utf8"))
#     inp = input(">>>>:")
#     conn.send(bytes(inp,"utf8"))
# conn.close()
conn.close()
服务端
技术分享
import socket
sk = socket.socket()
address = ("127.0.0.1",8000)
sk.connect(address)
while True:
    inp = input(">>>>:")
    if inp == "q":
        break
    sk.send(bytes(inp, "utf8"))
    date = sk.recv(1024)
    print(str(date,"utf8"))
sk.close()
客户端

简单的模拟qq对话(socket模块

技术分享
import socket,subprocess
sk = socket.socket()
address = (0.0.0.0,8000)
sk.bind(address)
sk.listen(2)
print("......")
while True:
    conn, addr = sk.accept()
    print(addr)
    while True:
        try:
            date = conn.recv(1024)
        except Exception:
            break
        if not date:break
        print(str(date, "utf8"))
        obj = subprocess.Popen(str(date, "utf8"),shell=True,stdout=subprocess.PIPE)
        cmd_result = obj.stdout.read()
        result_len = str(len(cmd_result))
        print(result_len)
        conn.send(bytes(result_len,"utf8"))
        conn.send(cmd_result)
    conn.close()
server
技术分享
import socket
sk = socket.socket()
address = ("127.0.0.1",8000)
sk.connect(address)
while True:
    inp = input(">>>>:")
    if inp == "q":
        break
    sk.send(bytes(inp, "utf8"))
    result_len = int(str(sk.recv(1024),"utf8"))
    print(result_len)
    date = bytes()
    while len(date) != result_len:
        da = sk.recv(1024)
        date+=da
    print(str(date,"gbk"))
sk.close()
client

简单的FTP上传图片

技术分享

技术分享
import subprocess
import socket
import os
sk=socket.socket()
print(sk)
address=(127.0.0.1,8000)
sk.bind(address)
sk.listen(3)
print(waiting......)
BASE_DIR=os.path.dirname(os.path.abspath(__file__))


while 1:
    conn, addr = sk.accept()
    while 1:
        data=conn.recv(1024)
        cmd,filename,filesize=str(data,utf8).split(|)
        path=os.path.join(BASE_DIR,tupian,filename)
        filesize=int(filesize)


        f=open(path,ab)

        has_receive=0
        while has_receive!=filesize:
            data=conn.recv(1024)
            f.write(data)
            has_receive+=len(data)

        f.close()
server
技术分享
import socket
import os
sk=socket.socket()
address=(127.0.0.1,8000)
sk.connect(address)

BASE_DIR=os.path.dirname(os.path.abspath(__file__))

while True:
    inp=input(>>>).strip()#   post|11.png

    cmd,path=inp.split(|)

    path=os.path.join(BASE_DIR,path)
    filename=os.path.basename(path)
    file_size=os.stat(path).st_size

    file_info=post|%s|%s%(filename,file_size)

    sk.sendall(bytes(file_info,utf8))

    f=open(path,rb)

    has_sent=0
    while has_sent!=file_size:
         data=f.read(1024)
         sk.sendall(data)
         has_sent+=len(data)

    f.close()
    print(上传成功)
client

 

以上是关于python学习笔记11 ----网络编程的主要内容,如果未能解决你的问题,请参考以下文章

Python学习笔记(11)日志

python学习笔记(11)--爬虫下载漫画图片

Python学习笔记__11章 正则表达式

Python学习笔记__12.11章 HTML Parser

python学习笔记(11)-语法要求(缩进标识符变量)

python基础学习笔记——Python基础教程(第2版 修订版)第11章(文件与素材)