python3 之 socket介绍

Python接口是套接字的Unix系统调用和库接口直接转换为Python的面向对象风格的socket()函数:该 函数返回一个套接字对象,其方法实现各种套接字系统调用

一、套接字
特定套接字对象所需的地址格式将根据套接字对象创建时指定的地址族自动选择。
1.AF_INET,一对用于地址族,其中host是表示Internet域表示法中的主机名的字符串,例如像IPv4地址,而port是整数。(host, port)
2.对于AF_INET6地址族,使用四元组,其中flowinfo和scopeid表示C中的成员 和成员。对于 模块方法,为了向后兼容,可以省略flowinfo和scopeid。但是,请注意,省略scopeid会导致操作范围内的IPv6地址时出现问题。(host, port, flowinfo, scopeid)sin6_flowinfosin6_scope_idstruct sockaddr_in6socket
3.AF_NETLINK套接字表示成对。(pid, groups)
4.使用AF_TIPC 地址系列可以使用仅支持TIPC的Linux 。TIPC是一种开放的,基于非IP的网络协议,设计用于集群计算机环境。地址由一个元组表示,并且这些字段取决于地址类型。一般的元组形式是 ,其中:(addr_type, v1, v2, v3 [, scope])

    ADDR_TYPE是一个TIPC_ADDR_NAMESEQ,TIPC_ADDR_NAME或TIPC_ADDR_ID。

    范围是一个TIPC_ZONE_SCOPE,TIPC_CLUSTER_SCOPE和 TIPC_NODE_SCOPE。

    如果addr_type是TIPC_ADDR_NAME,则v1是服务器类型,v2是端口标识符,并且v3应该是0。

    如果addr_type是TIPC_ADDR_NAMESEQ,则v1是服务器类型,v2 是较低的端口号,而v3是较高的端口号。

    如果addr_type是TIPC_ADDR_ID,则v1是节点,v2是参考,并且v3应该设置为0


    AF_ *和SOCK_ *常量现在AddressFamily和 SocketKind IntEnum集合。

二、常量
3.4版新增功能

    socket.AF_UNIX
    socket.AF_INET
    socket.AF_INET6
    这些常量表示用于第一个参数的地址(和协议)族socket()。如果AF_UNIX常量没有被定义,那么这个协议是不受支持的。取决于系统,可能有更多的常量。

    socket.SOCK_STREAM
    socket.SOCK_DGRAM
    socket.SOCK_RAW
    socket.SOCK_RDM
    socket.SOCK_SEQPACKET
    这些常量表示用于第二个参数的套接字类型 socket()。取决于系统,可能有更多的常量。(仅SOCK_STREAM和SOCK_DGRAM似乎是普遍有用的。)

    socket.SOCK_CLOEXEC
    socket.SOCK_NONBLOCK
    这两个常量(如果已定义)可以与套接字类型组合,并允许您以原子方式设置某些标志(从而避免可能的竞争条件和需要单独调用)。

socket 类型
套接字格式:
socket.socket(family = AF_INET,type = SOCK_STREAM,proto = 0,fileno = None )使用给定的地址簇、套接字类型,协议编号(默认为0)来创建套接字。

socket类型 描述
socket.AF_UNIX 只能够单一的unix系统进程通信
socket.AF_INET 服务器之间网络通信
socket.AF_INT6 IPv6
socket.SOCK_STREAM 流式socket,for TCP
socket.SOCK_DGRAM 数据报式socket,for UDP
socket.SOCK_RAW 原始套接字,普通的套接字无法处理ICMP、IGMP等网络报文,而SOCK_RAW可以;其次,SOCK_RAW也可以处理特殊IPv4报文;利用原始套接字可以通过IP_HDRINCL套接字选项由用户构造IP头。

|socket.SOCK_SEQPACKET |可靠的连续数据包服务|

创建TCP socket: s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)

创建UDP socket:s = socket.socket(socket.AF_INET,socket.SOCK_DGRAM

三、socket对象
  1. socket.accept()

    接受连接。套接字必须绑定到地址并监听连接。返回是一对:conn是一个新的套接字对象,可以用于在连接上发送和接收数据,address是绑定到连接另一端套接字的地址。(conn,address)。
    新创建的socket是不可以继承的。
  2. socket.bind(地址)

    地址的格式取决于地址族(address family ,family=AF_INET的格式元组(ip,port))
  3. socket.close()

    将socket标记为关闭
    socket在被垃圾收集时会自动关闭,但建议close()直接使用它。
    注意: close()释放与连接关联的资源,但不一定立即关闭连接。如果您想及时关闭连接,shutdown()
  4. socket.connect(address)

    连接到地址的远程套接字(地址的格式取决于address family)
  5. socket.getpeername()

    返回socket的远程地址。例如,找出远程IPv4/IPv6套接字的端口号。(返回地址的格式取决于地址族address family)
  6. socket.gettimeout()

    返回与套接字操作相关的超时秒数(浮点数),或者None 没有设置超时。
  7. socket.listen([backlog])

    启动服务器已接受连接,如果指定backlog,它必须至少为0;
  8. socket.makefile(mode=’r’,buffering=None,*,encoding=None,error = None,newline = None)

    返回与套接字关联的文件对象。确切的返回类型取决于给定的参数makefile(),这些参数的解释方式与内置open()函数的解释方式相同,只是唯一支持的模式值是’r’(默认)、’w’和 ‘b’。
    套接字必须处于阻塞模式;它可能有一个超时,但如果发生超时,文件的内部缓冲区可能会以不一致的状态结束。
    关闭通过返回的文件对象makefile()将不会关闭原始socket,除非所有其他文件对象已关闭且socket.close()已在socket对象上调用了。
  9. socket.recv(bufsize[,flags])

    从socket接收数据。返回值是一个表示接收到的数据字节对象( bytes objec)。一次接收的最大数据量由bufsize指定。默认为0,。
    注意:bufsize值,为了与硬件和网络实现最佳匹配,应该是2的幂次,例如4096
  10. socket.recvfrom(bufsize [,flags ])

    从socket接收数据。返回值是一对,其中bytes是表示接收数据的字节对象,address是发送数据的套接字的地址。有关可选参数标志的含义,请参阅Unix手册页recv(2) ; 它默认为零(地址的格式取决于地址族)(bytes, address)
  11. socket.send(bytes[,flags])

    Send data to the socket,socket必须连接到远程socket。可选参数flags。返回发送的字节数。应用程序负责检查所有数据是否已发送;如果只传输了一些数据,则应用程序需要阐释传送剩余的数据(利用while)
  12. socket.sendall(bytes[,flags])

    sendall和send的区别:sendall方法继续从字节发送数据,直到发送所有数据或发生错误。None成功返回。
  13. socket.sendfile(文件,偏移量= 0,计数=无)

    使用高性能发送文件直到达到EOF,os.sendfile并返回发送的字节总数。文件必须是以二进制模式打开的常规文件对象。如果os.sendfile不可用(例如Windows)或文件不是常规文件send()将被使用。偏移量指示从何处开始读取文件。如果指定,count是传输字节的总数,而不是发送文件直到达到EOF。返回时更新文件位置,或者在发生错误的情况下更新文件位置,在这种情况下file.tell()可用于计算发送的字节数。套接字必须是SOCK_STREAM类型的。非阻塞套接字不受支持。

    3.5版本中的新功能。

实例:
1、socket-server

import socket
import requests

def handle_index(client):
    buffer = client.recv(4096)
    client.send(b'HTTP/1.1 200 OK\r\n\r\n')
    f = open('templates/test.html','r',encoding='utf8')

    read_data = f.read().replace('var','baidu')
    print(read_data)
    client.send(bytes(read_data,encoding='utf8'))

def main():
    server = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
    server.bind(('localhost',8000))
    server.listen()
    while True:
        conn , addr = server.accept()
        handle_index(conn)
        print(addr)
        conn.close()
if __name__ =='__main__':
    main()

2、socket-client

import socket

client = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
client.connect(('localhost',8000))
client.send(b'hell,python!')

猜你喜欢

转载自blog.csdn.net/q936889811/article/details/80290466