Socket模块 网络编程

Socket介绍

Socket是计算机之间进行网络通信的一套程序接口,相当于在发送端和接收端之间建立了一个通信管道。在实际应用中,一些远程管理软件和网络安全软件大多依赖于Socket来实现特定功能。本篇主要讲解TCP(传输控制协议——在网络编程中应用的比较频繁)方式在网络编程中的具体应用实例以及代码详解!

socket.socket(family = AF_INET,type = SOCK_STREAM,proto = 0,fileno = None

family(协议族):
              AF_UNIX    用于单一的Unix系统进程间通信,要用一个绝对路径名作为地址
              AF_INET    默认IPV4
              AF_INET6   IPV6
tpye(类型):
           SOCK_STREAM  流式socket,TCP连接方式,默认参数
           SOCK_DGRAM   数据包式,不可靠UDP
           SOCK_RAW     处理特殊的IPv4报文 IGMP ICMP
           SOCK_RDM     可靠UDP形式
           SOCK_SEQPACKET  可靠的连续数据包服务
proto(协议):
           默认为0,表示会自动选择type类型对应的默认协议
           IPPROTO_TCP   TCP传输协议
           IPPROTO_UDP   UDP传输协议
           IPPROTO_STCP  STCP传输协议
           IPPROTO_TIPC  TIPC传输协议

socket常用函数

服务器端
函数名称               作用                                                        备注
bind((ip,port))绑定地址以元组方式(地址,端口)
listen(number) 开始监听number表示操作糸统可以挂起的最大连接数量,默认为1
server.accept()接受连接返回两个值,需要用两个变量来接收(conn, addr)每进来一个链接,服务端都会生成一个实例 conn用来接收这个实例,addr是链接的地址
客户端
connect(address)   连接远程计算机address的格式为元组:(ip,port)
connect_ex(address)connect相似远程连接只不过会有返回值,连接成功时返回 0 ,连接失败时候返回编码,例如:10061
通用函数
send(bytes[, flags]) 发送数据发送的为bytes字节模式,英文字符串前加b--> b'hello',中文要加encode---->"中文字符串".encode("utf-8"),  flags默认为空
sendall(bytes[,flag])   连续发送数据直到发送完所有数据或发生错误异常,并且无法确定成功发送了多少数据
sendto(bytesflagsaddress指定发送地址address为元组:(ip,port),指接收数据的套接字的远程地址
recv(bufsize[,flag])  接收数据返回值是一个字节对象,bufsize指定要接收的最大数据量,不可起过8193
recvfrom(bufsize[, flags])接收数据返回值是一对(bytes,addr) ,其中bytes是表示接收到的数据的字节对象,addr是发送数据的地址
close()      关闭
socket.detach()关闭套接字在未关闭文件描述符的情况下关闭,并返回文件描述符
dup()复制套接字
fileno()套接字的文件描述符返回socket的文件描述符(一个小整数),失败时返回 -1
get_inheritable()获取套接字的文件描述获取套接字的文件描述符或套接字句柄的可继承标志:如果套接字可以在子进程中继承,如果不能。TrueFalse
getpeername()返回套接字连接到的远程地址例如,这对于找出远程 IPv4/v6 套接字的端口号很有用。
getsockopt(level, optname[, buflen])返回给定套接字选项的值如果buflen不存在,则假定为整数选项,并且函数返回其整数值。如果buflen存在,它指定用于接收选项的缓冲区的最大长度,并且此缓冲区作为字节对象返回。
ioctl(control, option)控制套接字的模式(仅支持 Windows)
makefile(mode='r', buffering=None, *, encoding=None, errors=None, newline=None)
返回与套接字关联的文件对象
确切的返回类型取决于给 的参数。这些参数的解释方式与内置函数的解释方式相同
recvmsg(bufsize[, ancbufsize[, flags]])从socket接收普通数据最大bufsize字节)和辅助数据。ancbufsize参数设置用于接收辅助数据的内部缓冲区的大小(以字节为单位)它默认为 0,表示不会接收任何辅助数据。可以使用 或计算辅助数据的适当缓冲区大小,不适合缓冲区的项目可能会被截断或丢弃。
recvfrom_into(buffer[, nbytes[, flags]])  接收 UDP 消息到指定的缓冲区套接字接收数据,将其写入缓冲区而不是创建新的字节串。返回值是一对,其中nbytes是接收到的字节数,address是发送数据的套接字地址。
recv_into(buffer[, nbytes[, flags]])接收 TCP 消息到指定的缓冲区从socket接收最多nbytes字节,将数据存储到缓冲区而不是创建新的字节串。如果未指定nbytes (或 0),则接收最大为给定缓冲区中可用的大小
阻塞   面向阻塞的套接字方法
setblocking()设置套接字的阻塞或非阻塞模式

True如果套接字处于阻塞模式,则返回,如果处于非阻塞模式False

这相当于检查.socket.gettimeout() == 0

settimeout()设置阻塞套接字操作的超时时间返回与套接字操作关联的以秒为单位的超时(浮点数),或者None如果没有设置超时。
gettimeout()获取阻塞套接字操作的超时时间
文件方法      面向文件的套接字方法
fileno()套接字的文件描述符
makefile()创建与套接字关联的文件对象

简单通信TCP服务器

import socket
server = socket.socket()
server.bind(('localhost',6968)) #绑定地址
server.listen(5)  #开始监听,等待客户连接 监听5个
print("等响应")
while True:
    conn,addr = server.accept()   #响应客户端的一个请求 conn,addr用来接收accept返回的两个值,分别是对方的链接和地址
    print("客户端响应",addr)
    while True:
        data = conn.recv(1024)
        print("接收来自客户端发来的数据:",data.decode())    #接收客户端发来的数据,因为数据为bytes类型,所以decode()

        if not data :
            break
        input_0 = input(">>:").strip()
        conn.send(input_0.encode("utf-8"))  #向客户端发送数据
server.close()

简单通信TCP客户端

import socket
client = socket.socket()  ##声明socket类型,同时生成socket连接对象
client.connect(('localhost',6968))  #连接远程计算机
while True:
    input_0 = input(">>:").strip()
    if len(input_0) == 0:continue
    client.send(input_0.encode("utf-8"))  #发送给服务端的数据

    data = client.recv(1024)   #接收数据1024字节
    print("接收服务端发来的数据:",data.decode())
client.close()  #关闭

struct----将字节解释为打包的二进制数据

该模块定义了以下异常和函数:

exception struct.error

                                在各种场合引发的异常;argument 是描述错误的字符串。

struct.pack(formatv1v2...)

                     返回一个字节对象,第一个参数format格式字符串,v1v2 、…打包的值 。参数必须与格式所需的值完全匹配。

struct.pack_into(formatbufferoffsetv1v2...)

                                根据格式字符串format打包值v1v2 ,...,并将打包的字节写入从位置offset开始的可写缓冲区buffer中。请注意,offset是必需的参数。

struct.unpack(formatbuffer)

                                根据格式字符串格式从缓冲区buffer解压(大概是 packed by ) 。结果是一个元组,即使它只包含一个项目。缓冲区的大小(以字节为单位)必须与格式所需的大小相匹配,如.pack(format, ...)

struct.unpack_from(format/bufferoffset=0)

                                根据格式字符串格式,从位置offset开始的缓冲区中解包。结果是一个元组,即使它只包含一个项目。缓冲区的大小(以字节为单位)从位置offset开始,必须至少为格式所 需 的大小

struct.iter_unpack(formatbuffer)

                                根据格式字符串format迭代地从缓冲区buffer中解包。此函数返回一个迭代器,该迭代器将从缓冲区中读取相同大小的块,直到其所有内容都被消耗为止。缓冲区的大小(以字节为单位)必须是格式所需大小的倍数,如.calcsize()

struct.calcsize(format)

                                返回对应于格式字符串format的结构(以及由 生成的字节对象 )的大小。pack(format, ...)

struct中支持的格式

FormatC TypePython字节数
xpad byte  填充字节no value      没有值1
cchar     字符string of length 1  整数1
bsigned char    签名字符integer  整数1
Bunsigned char  无符号字符integer  整数1
?_Bool   _布尔bool  布尔 1
hshort   短的integer  整数2
Hunsigned short   无符号integer  整数2
iint   整数integer   整数4
Iunsigned int   无符号整数integer or long   整数4
llong    integer   整数4
Lunsigned long    无符号long   整数4
qlong long   长长long   整数8
Qunsigned long long   符号long  整数8
ffloat   浮点float   浮点4
ddouble   双倍的float  浮点8
schar[]    字符]string  1
pchar[]   字符]string1
Pvoid *   无效*long  整数

注1.q和Q只在机器支持64位操作时有意思

为了同c中的结构体交换数据,还要考虑有的c或c++编译器使用了字节对齐,通常是以4个字节为单位的32位系统,故而struct根据本地机器字节顺序转换.可以用格式中的第一个字符来改变对齐方式.定义如下:

CharacterByte orderSize and alignment
@native    本地native            凑够4个字节
=native    本地standard        按原字节数
<little-endian     小端standard        按原字节数
>big-endian      大端standard       按原字节数
!network (= big-endian)   网络(=大端)

standard       按原字节数

使用方法是放在fmt的第一个位置,就像'@5s6sif'

socketserver

简介

该模块简化了编写网络服务器的任务,SocketServer使用了select它有4个类:TCPServer,UDPServer,UnixStreamServer,UnixDatagramServer。这4个类是同步进行处理的,另外通过ForkingMixIn和ThreadingMixIn类来支持异步。

TCPServer ( server_address , RequestHandlerClass , bind_and_activate True )

                   TCP 协议,该协议在客户端和服务器之间提供连续的数据流。如果bind_and_activate为真,则构造函数会自动尝试调用server_bind() and server_activate()。其他参数传递给                        BaseServer基类。

UDPServer ( server_address , RequestHandlerClass , bind_and_activate True )

                    这使用数据报,它们是离散的信息包,可能会乱序到达或在传输过程中丢失。参数与 TCPServer相同

UnixStreamServer ( server_address , RequestHandlerClass , bind_and_activate True )   只能在Unix 平台上用。TCP  参数与 TCPServer相同  

UnixDatagramServer ( server_address , RequestHandlerClass , bind_and_activate True )   只能在Unix 平台上用。UDP  参数与 TCPServer相同

创建一个socketserver至少分以下几步:

首先,您必须创建一个请求处理类,并且通过继承BaseRequestHandler,再重写父类里的handle()方法

其次,先实例化其中一个服务器类(例:TCPServer),再传递 server ip 和上面创建的请求处理类给这个服务器类(例:TCPServer)。

然后调用服务器对象的 handle_request() 只处理一个请求 or serve_forever()处理多个请求 永远执行

最后,调用server_close() 关闭套接字(除非您使用with语句)。

class socketserver.BaseServer(server_address, RequestHandlerClass) 这是模块中所有服务器对象的超类。它定义了下面给出的接口,但没有实现大部分方法,这些方法是在子类中完成的。这两个参数存储在各自的 server_address和RequestHandlerClass属性中。

fileno() 文件描述 返回服务器正在侦听的套接字的整数文件描述符。此函数最常传递给selectors,以允许在同一进程中监视多个服务器。

handle_request() 处理单个请求

serve_forever(poll_interval=0.5) 处理请求,直到一个明确的shutdown()请求。每poll_interval秒轮询一次shutdown。忽略self.timeout。如果你需要做周期性的任务,建议放置在其他线程。

service_actions() 这在serve_forever()循环中被调用。此方法可以被子类或混合类覆盖,以执行特定于给定服务的操作,例如清理操作。

shutdown() 关机 告诉serve_forever()循环停止并等待其停止。

server_close() 服务器关闭 清理服务器。可能被覆盖。

address_family 地址家族,比如socket.AF_INET和socket.AF_UNIX。

RequestHandlerClass 用户提供的请求处理类,这个类为每个请求创建实例。

server_address 服务器侦听的地址。格式根据协议家族地址的各不相同,请参阅socket模块的文档。

allow_reuse_address 允许重用地址 服务器是否允许重复使用地址。这默认为 False,并且可以在子类中设置以更改策略。

request_queue_size 请求队列大小 请求队列的大小。如果处理单个请求需要很长时间,则在服务器繁忙时到达的任何请求都将放入队列中,直到request_queue_sizerequests。一旦队列已满,来自客户端的进 一步请求将收到“连接被拒绝”错误。默认值通常是 5,但可以被子类覆盖

socket_type 套接字类型 服务器使用的套接字类型;socket.SOCK_STREAM并且 socket.SOCK_DGRAM是两个共同的价值观。

timeout 超时 超时持续时间,以秒为单位,或者None如果不需要超时。如果handle_request()在超时期限内没有收到传入请求,handle_timeout()则调用该方法。

finish_request(request, client_address) 实际上通过实例化RequestHandlerClass和调用它的handle()方法来处理请求。

get_request() 必须接受来自套接字的请求,并返回一个二元组,其中包含 用于与客户端通信的新套接字对象,以及客户端的地址。

handle_error(request, client_address) handle() 如果实例的方法RequestHandlerClass引发异常,则调用此函数。默认操作是将回溯打印到标准错误并继续处理进一步的请求。

handle_timeout() 当该timeout属性被设置为除 之外的值None并且超时期限已过且未收到任何请求时,将调用此函数。分叉服务器的默认操作是收集任何已退出的子进程的状态,而在线程服务器中,此方法不执行任何操作。

process_request(request, client_address) 调用finish_request()以创建 的实例 RequestHandlerClass。如果需要,这个函数可以创建一个新的进程或线程来处理请求;theForkingMixIn和 ThreadingMixInclasses 做这个。

server_activate() 由服务器的构造函数调用以激活服务器。TCP 服务器的默认行为只是调用listen() 服务器的套接字。可能被覆盖。

server_bind() 由服务器的构造函数调用以将套接字绑定到所需的地址。可能被覆盖。

verify_request(request, client_address) 必须返回一个布尔值;如果值为True,请求将被处理,如果是False,请求将被拒绝。可以重写此函数以实现对服务器的访问控制。默认实现总是返回True。 请求处理程序对象

class socketserver.BaseRequestHandler

setup() 设置 handle()在执行所需的任何初始化操作的方法之前调用。默认实现什么也不做。

handle() 句柄 此功能必须完成为请求提供服务所需的所有工作。默认实现什么也不做。它有几个实例属性;该请求可作为self.request;客户地址为self.client_address;和服务器实例

self.server,以防它需要访问每个服务器的信息。 finish() 完成 handle()在执行所需的任何清理操作的方法之后调用。默认实现什么也不做。如果setup() 引发异常,则不会调用此函数。

import socketserver
class MyTCPHandler(socketserver.BaseRequestHandler):
    def handle(self):    #在父类里为空,跟客服端所有的交接都在handle里写的
        print("客户端IP%s" % (self.client_address[0]))  # 打印客户端 ip地址
        while True:
            self.data = self.request.recv(1024).strip()         #收 实例化接收对象
            print(self.data)
            len_data = len(self.data)
            print(len_data)
            self.request.send(self.data.upper())    #发
            if not self.data:break

"if name == ‘main’ 我们简单的理解就是: 如果模块是被直接运行的,则if __name__ == '__main__'下的代码块被运行;" \
"如果该模块被其他程序导入,则if __name__ == '__main__'下的代码块不被运行。"
if __name__ == "__main__":
    HOST, PORT = "localhost", 9995  #创建服务器,并绑定到端口9999上的本地主机
    #socketserver.TCPServer((HOST, PORT), MyTCPHandler)
    server = socketserver.ThreadingTCPServer((HOST, PORT), MyTCPHandler)   #第2步修改ThreadingTCPServer,进行多并发
    server.serve_forever()

  • 10
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值