python第八周学习内容

1.socket网络编程

1.1概念:

网络套接字是跨计算机网络的连接的端点。今天,计算机之间的大多数通信都基于互联网协议;因此大多数网络套接字都是Internet套接字。更准确地说,套接字是一个句柄(抽象引用),本地程序可以将其传递给网络应用程序编程接口(API)以使用该连接,例如“在此套接字上发送此数据”。

例如,发送“Hello,world!”通过TCP到地址为1.2.3.4的主机的端口80,可以获得一个套接字,将其连接到远程主机,发送字符串,然后关闭套接字。

实现一个socket至少要分以下几步,(伪代码):

1.Socket socket = getSocket(type = "TCP"#设定好协议类型

2.connect(socket, address = "1.2.3.4", port = "80") #连接远程机器

3.send(socket, "Hello, world!") #发送消息

4.close(socket) #关闭连接

套接字API是一种应用程序编程接口(API),通常由操作系统提供,允许应用程序控制和使用网络套接字。 Internet套接字API通常基于Berkeley套接字标准。在Berkeley套接字标准中,套接字是文件描述符(文件句柄)的一种形式,由于Unix哲学“一切都是文件”,以及套接字和文件之间的类比:你可以读,写,打开和关闭。

套接字地址是IP地址和端口号的组合,很像电话连接的一端是电话号码和特定分机的组合。 套接字不需要有地址(例如仅用于发送数据),但如果程序将套接字绑定到地址,则套接字可用于接收发送到该地址的数据。 基于此地址,Internet套接字将传入的数据包传递到适当的应用程序进程或线程

Socket Families(地址簇)

socket.AF_UNIX unix本机进程间通信

socket.AF_INET IPV4 

socket.AF_INET6  IPV6

这些常量表示用于socket()的第一个参数的地址(和协议)系列。 如果未定义AF_UNIX常量,则不支持此协议。 根据系统的不同,可能会有更多常量可用。

Socket Types

socket.SOCK_STREAM  #for tcp

socket.SOCK_DGRAM  #for udp

socket.SOCK_RAW   #原始套接字,普通的套接字无法处理ICMP、IGMP等网络报文,而SOCK_RAW可以;其次,SOCK_RAW也可以处理特殊的IPv4报文;此外,利用原始套接字,可以通

          过IP_HDRINCL套接字选项由用户构造IP头。

socket.SOCK_RDM  #是一种可靠的UDP形式,即保证交付数据报但不保证顺序。SOCK_RAM用来提供对原始协议的低级访问,在需要执行某些特殊操作时使用,如发送ICMP报文。

          SOCK_RAM通常仅限于高级用户或管理员运行的程序使用。

socket.SOCK_SEQPACKET #废弃了

这些常量表示套接字类型,用于socket()的第二个参数。 根据系统的不同,可能会有更多常量可用。 (只有SOCK_STREAM和SOCK_DGRAM似乎通常很有用。)

1.2 Socket 参数

(1)socket.socket(family=AF_INETtype=SOCK_STREAMproto=0fileno=None)  必会

使用给定的地址系列,套接字类型和协议号创建一个新套接字。 地址族应为AF_INET(默认值),AF_INET6,AF_UNIX,AF_CAN或AF_RDS。 套接字类型应该是SOCK_STREAM(默认值),SOCK_DGRAM,SOCK_RAW或者其他SOCK_常量之一。 协议号通常为零并且可以省略,或者在地址族是AF_CAN的情况下,协议应该是CAN_RAW或CAN_BCM之一。 如果指定了fileno,则忽略其他参数,从而返回具有指定文件描述符的套接字。 与socket.fromfd()不同,fileno将返回相同的套接字而不是重复。 这可能有助于使用socket.close()关闭分离的套接字。

(2)socket.socketpair([family[, type[, proto]]])

使用给定的地址系列,套接字类型和协议编号构建一对连接的套接字对象。 地址族,套接字类型和协议号与上面的socket()函数相同。 如果在平台上定义,则默认系列为AF_UNIX; 否则,默认为AF_INET。

(3)socket.create_connection(address[, timeout[, source_address]])

连接到侦听Internet地址(2元组(主机,端口))的TCP服务,并返回套接字对象。 这是一个比socket.connect()更高级的函数:如果host是非数字主机名,它将尝试为AF_INET和AF_INET6解析它,然后尝试依次连接到所有可能的地址,直到连接成功。 这样可以轻松编写与IPv4和IPv6兼容的客户端。

传递可选的timeout参数将在尝试连接之前设置套接字实例上的超时。 如果未提供超时,则使用getdefaulttimeout()返回的全局默认超时设置。

如果提供,则source_address必须是要连接的套接字的2元组(主机,端口)作为其源地址才能连接。 如果主机或端口分别为‘或0,则将使用OS默认行为。

(4) socket.getaddrinfo(hostportfamily=0type=0proto=0flags=0) #获取要连接的对端主机地址

(5) sk.bind(address) 必会

sk.bind(address) 将套接字绑定到地址。address地址的格式取决于地址族。在AF_INET下,以元组(host,port)的形式表示地址。

(6) sk.listen(backlog) 必会

开始监听传入连接。backlog指定在拒绝连接之前,可以挂起的最大连接数量。backlog等于5,表示内核已经接到了连接请求,但服务器还没有调用accept进行处理的连接个数最大为5。这个值不能无限大,因为要在内核中维护连接队列

(7)sk.setblocking(bool) 必会

是否阻塞(默认True),如果设置False,那么accept和recv时一旦无数据,则报错。

(8) sk.accept() 必会

接受连接并返回(conn,address),其中conn是新的套接字对象,可以用来接收和发送数据。address是连接客户端的地址。接收TCP 客户的连接(阻塞式)等待连接的到来

(9)sk.connect(address) 必会

连接到address处的套接字。一般,address的格式为元组(hostname,port),如果连接出错,返回socket.error错误。

(10)sk.connect_ex(address)

同上,只不过会有返回值,连接成功时返回 0 ,连接失败时候返回编码,例如:10061

(11)sk.close() 必会

关闭套接字

(12)sk.recv(bufsize[,flag]) 必会

接受套接字的数据。数据以字符串形式返回,bufsize指定最多可以接收的数量。flag提供有关消息的其他信息,通常可以忽略。

(13)sk.recvfrom(bufsize[.flag])

与recv()类似,但返回值是(data,address)。其中data是包含接收数据的字符串,address是发送数据的套接字地址。

(14)sk.send(string[,flag]) 必会

将string中的数据发送到连接的套接字。返回值是要发送的字节数量,该数量可能小于string的字节大小。即:可能未将指定内容全部发送。

(15)sk.sendall(string[,flag]) 必会

将string中的数据发送到连接的套接字,但在返回之前会尝试发送所有数据。成功返回None,失败则抛出异常。内部通过递归调用send,将所有内容发送出去。

(16)sk.sendto(string[,flag],address)

将数据发送到套接字,address是形式为(ipaddr,port)的元组,指定远程地址。返回值是发送的字节数。该函数主要用于UDP协议。

(17)sk.settimeout(timeout) 必会

设置套接字操作的超时期,timeout是一个浮点数,单位是秒。值为None表示没有超时期。一般,超时期应该在刚创建套接字时设置,因为它们可能用于连接的操作(如 client 连接最多等待5s )

(18)sk.getpeername()  必会

返回连接套接字的远程地址。返回值通常是元组(ipaddr,port)。

(19)sk.getsockname()

返回套接字自己的地址。通常是一个元组(ipaddr,port)

(20)sk.fileno() 

套接字的文件描述符

(21)socket.sendfile(fileoffset=0count=None)

发送文件 ,但目前多数情况下并无什么卵用。

1.3 通过socket实现简单的ssh

程序流程如下:

程序代码:

socket_server端:

import socket,os

server = socket.socket()
server.bind(("localhost",9999))
server.listen()
while True:
    conn,addr = server.accept() #阻塞
    while True:
        print("wait for new cmd:")
        cmd = conn.recv(1024).decode()
        if not cmd:
            print("客户端已断开")
            break
        cmd_result = os.popen(cmd).read()
        if len(cmd_result) == 0:
            cmd_result = "这条命令错误"
            length = len(cmd_result.encode("utf-8"))
        length = len(cmd_result.encode("utf-8"))
        conn.send(str(length).encode("utf-8"))
        conn.recv(1024)
        conn.send(cmd_result.encode("utf-8"))
server.close()

socket_client端:

import socket

client = socket.socket()
client.connect(("localhost",9999))
while True:
    cmd = input("输入指令:")
    if len(cmd) == 0:
        continue
    client.send(cmd.encode("utf-8"))
    length = client.recv(1024).decode()
    print("命令结果大小:",length)
    receive_size = 0
    receive_data = b""
    client.send(b"OK")
    while receive_size < int(length):
        data = client.recv(1024)
        receive_size += len(data)
        receive_data += data
    print("命令结果实际大小:",receive_size)
    print(receive_data.decode())
client.close()

程序运行结果:

#server端:
wait for new cmd:
ipconfig
wait for new cmd:

#client端:
输入指令:ipconfig
命令结果大小: 1680
命令结果实际大小: 1680

Windows IP 配置

以太网适配器 以太网:

   媒体状态  . . . . . . . . . . . . : 媒体已断开连接
   连接特定的 DNS 后缀 . . . . . . . : 

无线局域网适配器 本地连接* 3:

   媒体状态  . . . . . . . . . . . . : 媒体已断开连接
   连接特定的 DNS 后缀 . . . . . . . : 

无线局域网适配器 本地连接* 12:

   媒体状态  . . . . . . . . . . . . : 媒体已断开连接
   连接特定的 DNS 后缀 . . . . . . . : 

以太网适配器 VMware Network Adapter VMnet1:

   连接特定的 DNS 后缀 . . . . . . . :
   本地链接 IPv6 地址. . . . . . . . : fe80::7ddd:a3e4:9673:512e%7
   IPv4 地址 . . . . . . . . . . . . : 192.168.74.1
   子网掩码  . . . . . . . . . . . . : 255.255.255.0
   默认网关. . . . . . . . . . . . . : 

以太网适配器 VMware Network Adapter VMnet8:

   连接特定的 DNS 后缀 . . . . . . . :
   本地链接 IPv6 地址. . . . . . . . : fe80::4cc1:5dc2:37f:7e7b%17
   IPv4 地址 . . . . . . . . . . . . : 192.168.43.1
   子网掩码  . . . . . . . . . . . . : 255.255.255.0
   默认网关. . . . . . . . . . . . . : 

无线局域网适配器 WLAN:

   连接特定的 DNS 后缀 . . . . . . . :
   IPv6 地址 . . . . . . . . . . . . : 2001:da8:215:8f01:8d1d:db29:3fd2:c6d6
   临时 IPv6 地址. . . . . . . . . . : 2001:da8:215:8f01:dc75:865e:ccf6:e781
   本地链接 IPv6 地址. . . . . . . . : fe80::8d1d:db29:3fd2:c6d6%10
   IPv4 地址 . . . . . . . . . . . . : 10.122.252.64
   子网掩码  . . . . . . . . . . . . : 255.255.192.0
   默认网关. . . . . . . . . . . . . : fe80::274:9cff:fe7d:fadb%10
                                       10.122.192.1

输入指令:

1.4 通过socket实现简单的ftp server

1.读取文件名2.检测文件是否存在3.打开文件4.检测文件大小5.发送文件大小和md5给客户端6.等客户端确认7.开始边读边发数据8.md59.关闭文件程序代码:客户端:
# -*- coding:utf-8 -*-
#!/user/bin/env.python
#Author:Mr Wu

‘‘‘FTP Server‘‘‘
import socket,os,hashlib

server = socket.socket()
server.bind(("localhost",1999))
server.listen()
while True:
    conn,addr = server.accept() #阻塞
    while True:
        data = conn.recv(1024).decode()
        if not data:
            print("客户端已断开连接!")
            break
        file_cmd,file_name = data.split()
        if os.path.isfile(file_name):
            file_size = os.stat(file_name).st_size
            conn.send(str(file_size).encode("utf-8"))
            conn.recv(1024) #避免粘包
            m = hashlib.md5()
            f = open(file_name,"rb")
            print("开始发送文件.....")
            for line in f:
                m.update(line)
                conn.send(line)
            f.close()
            print("发送md5.......")
            conn.send(m.hexdigest().encode("utf-8"))
server.close()
服务端:
# -*- coding:utf-8 -*-
#!/user/bin/env.python
#Author:Mr Wu

import socket,os,hashlib

client = socket.socket()
client.connect(("localhost",1999))
while True:
    cmd = input("输入文件名[格式:get 文件名]>>>:").strip()
    if len(cmd) == 0:
        continue
    if cmd.startswith("get"):
        file_name = cmd.split()[1]
        client.send(cmd.encode("utf-8"))
        data = client.recv(1024)
        file_total_size = int(data.decode())
        client.send(b"OK")
        file_size = 0
        f = open(file_name,"wb")
        m = hashlib.md5()
        while file_size < file_total_size:
            last_size = file_total_size - file_size
            if last_size < 1024:
                size = last_size
            else:
                size = 1024
            ‘‘‘避免粘包‘‘‘
            data = client.recv(size)
            m.update(data)
            f.write(data)
            file_size =+ len(data)
        f.close()
        md5 = m.hexdigest()
        received_md5 = client.recv(1024).decode()
        if md5 == received_md5:
            print("文件md5一致,传输成功!")
        else:
            print("文件传输错误!")
    else:
        print("输入格式错误!")
        continue
运行结果:
server端:
开始发送文件.....
发送md5.......
client端:
输入文件名[格式:get 文件名]>>>:get test.py
文件md5一致,传输成功!

2.socketServer的使用

注:由于其涉及线程的相关知识(还未学习),在学习完线程之后,再来写socketServer的相关概念2.1 使用方法:(1)你必须自己创建一个处理类,并且这个类要继承BaseRequestHandler,并且还要重写父类里的handle()(2)你必须实例化TCPServer,并且传递server ip和你上面创建的请求处理类给这个TCPServer(3)server.handle_request() #只处理一个请求     server.serve_forever() #处理多个连接请求,永远执行2.2 SocketServer程序示例:
# -*- coding:utf-8 -*-
#!/user/bin/env.python
#Author:Mr Wu

import socketserver
class MyTCPHandler(socketserver.BaseRequestHandler):
    ‘‘‘每一个请求过来都会实例化MyTCPHandler‘‘‘
    def handle(self):
        ‘‘‘与客户端所有的交互都是在handle里完成的‘‘‘
        while True:
            try:
                self.data = self.request.recv(1024).strip()
                print("{} wrote:".format(self.client_address[0]))
                print(self.data)
                #if not self.data:
                #    print("客户端断开连接")
                #    break
                #just send the same data,but upper-cased
                self.request.send(self.data.upper())
            except ConnectionResetError as e:
                print(e)
                break
if __name__ == "__main__":
    HOST,PORT = "localhost",9999
    #create the server,binding to localhost on port 9999
    server = socketserver.ThreadingTCPServer((HOST,PORT),MyTCPHandler)
    ‘‘‘
    activate the server:this will keep running until you
    interrupt the program with Ctrl-C
    ‘‘‘
    server.serve_forever() #处理多个请求,即可以连接多个客户端
未完待续。。。。。。。。


原文地址:https://www.cnblogs.com/BUPT-MrWu/p/9903544.html

时间: 2024-11-07 14:24:46

python第八周学习内容的相关文章

python第三周学习内容

1.集合: 集合的创建: list_1 = set([1,2,3,4,5]) list_2 = set([2,3,44,7,8]) 集合的特性:集合是无序的,集合可以去掉重复的元素 集合的操作:求交集: print(list_1.intersection(list_2)) #{2,3} print(list_l & list_2) #求交集,{2,3} 求并集: print(list_1.union(list_2)) #{1,2,3,4,5,7,8,44} print(list_l | list

Python第八周 学习笔记(1)

继承 基本概念个体继承自父母,继承了父母的一部分特征,但也可以有自己的个性 子类继承了父类,就直接拥有了父类的属性和方法,也可以定义自己的属性.方法,甚至对父类的属性.方法进行重写 Python继承实现 class Cat(Animal) 括号中为该类的父类列表 如果类定义时没有父类列表,则只继承object类 object类是所有类的祖先类 类的特殊属性与方法 base 类的基类 bases 类的基类的元组 mro 方法解析时的类的查找顺序,返回元组 mro() 作用同上,返回列表 subcl

《Java》第八周学习总结

第八周学习内容:课本第15章节的内容泛型与集合框架  主要内容有 -泛型-链表-堆栈-散列映射-树集-树映射 重点和难点-重点:泛型和集合的使用码云:https://gitee.com/ShengHuoZaiDaXue/20175301.git 调试代码 遇见问题 散列映射的查询无法实现 查询ppt以后理解 学习进度条 代码行数 博客量 目标6000 目标30 456/3112 5/14 原文地址:https://www.cnblogs.com/lijinran/p/10745370.html

20145301 《Java程序设计》第八周学习总结

20145301 <Java程序设计>第八周学习总结 教材学习内容总结 第十五章部分 - 通用API 通用API 日志: 日志对信息安全意义重大,审计.取证.入侵检测等都会用到日志信息 Logger java.util.logging包提供了日志功能相关类与接口,使用日志的起点是logger类,Logger类的构造函数标示为protected,不是java.util.logging同包的类不能直接以new创建,必许使用Logger的静态方法:名称空间层级相同的Logger,父Logger组态会

《Linux内核设计与实现》第八周学习总结——第四章 进程调度

<Linux内核设计与实现>第八周学习总结——第四章 进程调度 第4章 进程调度35 调度程序负责决定将哪个进程投入运行,何时运行以及运行多长时间,进程调度程序可看做在可运行态进程之间分配有限的处理器时间资源的内核子系统.只有通过调度程序的合理调度,系统资源才能最大限度地发挥作用,多进程才会有并发行的效果. 调度程序没有太复杂的原理,最大限度地利用处理器时间的原则是只要有可以执行的进程,那么就总会有进程正在执行,但是只要系统中可运行的进程的数目比处理器的个数多,就注定某一给定时刻会有一些进程不

## 20155336 2016-2017-2《JAVA程序设计》第八周学习总结

20155336 2016-2017-2<JAVA程序设计>第八周学习总结 教材学习内容总结 第14章 NIO与NIO2 NIO简介 NIO使用频道来衔接数据结点,在处理数据时,NIO可以让你设定缓冲区容量,在缓冲区中对感兴趣的数据区块进行标记,像是标记读取位 置.数据有效位置,对于这些区块标记,提供了Clear().rewind().flip().compact()等高级操作. NIO2简介 NIO2文件系统API提供一组标准接口与类,应用程序开发者只要基于这些标准接口与类进行文件系统操作,

LINUX内核分析第八周学习总结——进程的切换和系统的一般执行过程

LINUX内核分析第八周学习总结——进程的切换和系统的一般执行过程 黄韧(原创作品转载请注明出处) <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 一.知识概要 Linux中进程调度的基本概念与相关知识 schedule函数如何实现进程调度 Linux进程的执行过程(一般情况与特殊情况) 宏观描述Linux系统执行 二.学习笔记 (一)进程切换的关键代码switch_to分析 进程进度与进程调度的时机分析 1.

2017-2018-20155336 《信息安全系统设计基础》第八周学习总结

2017-2018-20155336 <信息安全系统设计基础>第八周学习总结 教材学习内容总结 第11章网络编程 1.客户端-服务器编程模型 一个服务器进程 -> 管理某种资源 -> 通过操作这种资源来为它的客户端提供某种服务 一个或多个客户端进程 基本操作:事务 当一个客户端需要服务时,向服务器发送一个请求,发起一个事务. 服务器收到请求后,解释它,并以适当的方式操作它的资源. 服务器给客户端发送一个相应,并等待下一个请求. 客户端收到响应并处理它. 客户端和服务器都是进程. 2

2017-2018-1 20155317《信息安全系统设计基础》第八周学习总结

2017-2018-1 20155317<信息安全系统设计基础>第八周学习总结 教材学习内容总结 并发 进程间可以并发执行. 同属一个进程的多个线程,也可以并发执行. 线程时操作系统拥有更好的并发性,从而能有效地使用系统资源和提供系统吞吐量. 当一个未引入线程的单处理机操作系统,若设置一个文件服务进程,当它由于某种原因阻塞,便没有其他的文件服务进程来提供服务.引入线程以后,可以为一个文件服务进程中设置多个服务线程,当其中一个线程阻塞时,文件服务进程中的其他线程可以继续运行,提供了文件服务的质量