python3.x 基础八:socket网络编程
Socket
socket就是一直以来说的“套接字”,用于描述:ip:端口,是通信链的句柄,客户端通过这个句柄进行请求和响应
- 普通文件的操作顺序:打开-读写-关闭,针对的是文件
- socket是特殊的文件,操作顺序也是:打开-请求/相应-关闭,针对的是Client和Server之间的socket
整过过程如下:
socket方法
| bind(...)
| bind(address)
|
| Bind the socket to a local address. For IP sockets, the address is a
| pair (host, port); the host must refer to the local host. For raw packet
| sockets the address is a tuple (ifname, proto [,pkttype [,hatype]])
- 将套接字绑定大地址,如果是raw包,地址是元组形式(ip,port)
| close(...)
| close()
|
| Close the socket. It cannot be used after this call.
- 关闭套接字
| connect(...)
| connect(address)
|
| Connect the socket to a remote address. For IP sockets, the address
| is a pair (host, port).
- 链接到远程地址,如果是IP socket,地址是元组形式(ip,port)
| connect_ex(...)
| connect_ex(address) -> errno
|
| This is like connect(address), but returns an error code (the errno value)
| instead of raising an exception when an error occurs.
- 同connect,当发生错误时返回错误代码,而不是异常
| detach(...)
| detach()
|
| Close the socket object without closing the underlying file descriptor.
| The object cannot be used after this call, but the file descriptor
| can be reused for other purposes. The file descriptor is returned.
- 关闭套接字对象,而不关闭文件描述符,文件描述符类似文件句柄
| fileno(...)
| fileno() -> integer
|
| Return the integer file descriptor of the socket.
- 返回文件描述符
| getpeername(...)
| getpeername() -> address info
| Return the address of the remote endpoint. For IP sockets, the address
| info is a pair (hostaddr, port).
- 返回套接字的远程地址,一般是元组形式(ip,port)
| getsockname(...)
| getsockname() -> address info
|
| Return the address of the local endpoint. For IP sockets, the address
| info is a pair (hostaddr, port).
- 返回套接字自己的地址,一般是元组形式(ip,port)
| getsockopt(...)
| getsockopt(level, option[, buffersize]) -> value
|
| Get a socket option. See the Unix manual for level and option.
| If a nonzero buffersize argument is given, the return value is a
| string of that length; otherwise it is an integer.
- 获取套接字的选项
| gettimeout(...)
| gettimeout() -> timeout
|
| Returns the timeout in seconds (float) associated with socket
| operations. A timeout of None indicates that timeouts on socket
| operations are disabled.
- 以秒返回套接字操作超时时间
| listen(...)
| listen([backlog])
|
| Enable a server to accept connections. If backlog is specified, it must be
| at least 0 (if it is lower, it is set to 0); it specifies the number of
| unaccepted connections that the system will allow before refusing new
| connections. If not specified, a default reasonable value is chosen.
- 使server端开始监听链接,backlog至少未0,指定了尚未被accept处理的连接个数,如果达到这个数目,后面的连接将被拒绝,如果不指定,系统会设置一个合理值
| recv(...)
| recv(buffersize[, flags]) -> data
|
| Receive up to buffersize bytes from the socket. For the optional flags
| argument, see the Unix manual. When no data is available, block until
| at least one byte is available or until the remote end is closed. When
| the remote end is closed and all data is read, return the empty string.
- 从套接字中能接收到的数据,buffersize指定最多可以接收的大小,以bytes形式返回
| recv_into(...)
| recv_into(buffer, [nbytes[, flags]]) -> nbytes_read
|
| A version of recv() that stores its data into a buffer rather than creating
| a new string. Receive up to buffersize bytes from the socket. If buffersize
| is not specified (or 0), receive up to the size available in the given buffer.
|
| See recv() for documentation about the flags.
- 与recv类似,保存数据到缓存,而不是创建接收字符串
| recvfrom(...)
| recvfrom(buffersize[, flags]) -> (data, address info)
|
| Like recv(buffersize, flags) but also return the sender's address info.
- 与recv类似,返回值是元组形式(data,address),data是包含接收数据的字符串,address是发送数据的套接字地址
| recvfrom_into(...)
| recvfrom_into(buffer[, nbytes[, flags]]) -> (nbytes, address info)
|
| Like recv_into(buffer[, nbytes[, flags]]) but also return the sender's address info.
- 与recv_into类似,返回的是发送者的地址信息
| recvmsg(...)
| recvmsg(bufsize[, ancbufsize[, flags]]) -> (data, ancdata, msg_flags, address)
| recvmsg_into(...)
| recvmsg_into(buffers[, ancbufsize[, flags]]) -> (nbytes, ancdata, msg_flags, address)
| sendall(...)
| sendall(data[, flags])
|
| Send a data string to the socket. For the optional flags
| argument, see the Unix manual. This calls send() repeatedly
| until all data is sent. If an error occurs, it's impossible
| to tell how much data has been sent.
- 循环发送,直到发送完毕
| sendmsg(...)
| sendmsg(buffers[, ancdata[, flags[, address]]]) -> count
|
| Send normal and ancillary data to the socket, gathering the
| non-ancillary data from a series of buffers and concatenating it into
| a single message. The buffers argument specifies the non-ancillary
| data as an iterable of bytes-like objects (e.g. bytes objects).
| The ancdata argument specifies the ancillary data (control messages)
| as an iterable of zero or more tuples (cmsg_level, cmsg_type,
| cmsg_data), where cmsg_level and cmsg_type are integers specifying the
| protocol level and protocol-specific type respectively, and cmsg_data
| is a bytes-like object holding the associated data. The flags
| argument defaults to 0 and has the same meaning as for send(). If
| address is supplied and not None, it sets a destination address for
| the message. The return value is the number of bytes of non-ancillary
| data sent.
|
| sendto(...)
| sendto(data[, flags], address) -> count
|
| Like send(data, flags) but allows specifying the destination address.
| For IP sockets, the address is a pair (hostaddr, port).
- 类似send,将数据发送到套接字,指定远端目标地址,返回的是发送字节数,多用于UDP协议
| setblocking(...)
| setblocking(flag)
|
| Set the socket to blocking (flag is true) or non-blocking (false).
| setblocking(True) is equivalent to settimeout(None);
| setblocking(False) is equivalent to settimeout(0.0).
- 是否阻塞,默认是True,等同settimeout(None),如果是False,accept和recv时无数据则报错,等同于settimeout(0.0)
| setsockopt(...)
| setsockopt(level, option, value)
|
| Set a socket option. See the Unix manual for level and option.
| The value argument can either be an integer or a string.
- 设置套接字选项,值参数可以是整形或者字符串
| settimeout(...)
| settimeout(timeout)
|
| Set a timeout on socket operations. 'timeout' can be a float,
| giving in seconds, or None. Setting a timeout of None disables
| the timeout feature and is equivalent to setblocking(1).
| Setting a timeout of zero is the same as setblocking(0).
- 设置套接字操作的超时时间,timeout是一个浮点数秒,None表示没有超时,指定超时时间等同setblocking(1),就是阻塞,如果没有超时间等同setblock(0)
| shutdown(...)
| shutdown(flag)
|
| Shut down the reading side of the socket (flag == SHUT_RD), the writing side
| of the socket (flag == SHUT_WR), or both ends (flag == SHUT_RDWR).
- 关闭socket读的一端或者写的一端,或者同时关闭两端
client:
import socket client=socket.socket() # 实例化一个socket类,同时生成socket链接对象 client.connect(('localhost',8080)) # 链接目标,元组类型的主机+端口 while True: msg=input('pls input something>>').strip() if not bool(msg): print('未输入任何内容') continue client.send(msg.encode("utf-8")) # 指定编码格式utf-8 ,发送数据,python3只能发送byte类型 data=client.recv(1024) # 接受窗口缓存大小,如果接收的内容大于窗口,则服务器的发送缓存会一直发送过来 print(data.decode()) # 将byte类型转换成unicode client.close()
1.发送字符串
接收客户端请求,并返回结果的server:
import socket server=socket.socket() server.bind(('localhost',8080)) # 服务端绑定监听主机+端口 server.listen() #监听 while True: print('begin to listening...') conn,addr=server.accept() #server.accept 等待链接进来,如果没有链接进来,则一直阻塞在这里 #不能用data=server。accept()直接接收,多个链接进来会无法区分是哪个链接 #使用标记方法,accept会返回两个值,一个是标记位,就是socket的句柄,一个是链接地址 print('conn:%s \n adr:%s'%(conn,addr)) print('conntion is coming') while True: data=conn.recv(1024) # 设置socket句柄接收的窗口大小 print('recv:',data.decode('utf-8')) if not data: print('client is lost') break conn.send(data.upper()) # 发送请求结果给客户端 server.close()
2.发送linux命令
返回命令结果给客户端
import os import socket server=socket.socket() server.bind(('localhost',8020)) server.listen() while True: print('begin to listening...') conn, addr = server.accept() # print('conn:%s \n adr:%s' % (conn, addr)) print('conntion is coming') while True: data = conn.recv(1024) print('I had recv your request %s'%data) data=str(data,encoding="utf-8") print('data is %s'%data) print('change byte to str',data) if not data: print('client is lost') break res=os.popen(data).read() conn.send(bytes(res,encoding="utf-8")) print(len(data)) server.close()
3.传送文件
client
import socket client=socket.socket() # 实例化一个socket类,同时生成socket链接对象 client.connect(('localhost',8010)) # 链接目标,元组类型的主机+端口 fd=open('../file.zip','wb') while True: msg=input('pls input something>>').strip() if not bool(msg): print('未输入任何内容') continue client.send(msg.encode("utf-8")) # 指定编码格式utf-8 ,发送数据,python3只能发送byte类型 # data=client.recv(1024) # 接受窗口缓存大小,如果接收的内容大于窗口,则服务器的发送缓存会一直发送过来 file=client.recv(10240000) print('recv size is ',len(file)) fd.write(file) fd.flush() client.close()
server
import socket server=socket.socket() server.bind(('localhost',8010)) server.listen() while True: print('begin to listening...') conn, addr = server.accept() print('conn:%s \n adr:%s' % (conn, addr)) print('conntion is coming') while True: data = conn.recv(1024) print('I had recv your request %s'%data) data=str(data,encoding="utf-8") print('change byte to str',data) if not data: print('client is lost') break with open('../MDMCSL71008_40-20004526.ZIP','rb') as fdr: file=fdr.read() print('file size is ',len(file)) conn.sendall(file) print('file had ben sent') break server.close()
注意:接收和发送的缓存有上限,大文件不能一次发送过来或者一次接收