Python网络编程

网络编程通信流程

sk.bind(address)
  # s.bind(address) 将套接字绑定到地址。address地址的格式取决于地址族。在AF_INET下,以元组(host,port)的形式表示地址。
sk.listen(backlog)
  # 开始监听传入连接。backlog指定在拒绝连接之前,可以挂起的最大连接数量。
sk.setblocking(bool)
  # 是否阻塞(默认True),如果设置False,那么accept和recv时一旦无数据,则报错。
sk.accept()
  # 接受连接并返回(conn,address),其中conn是建立连接的套接字对象,可用于数据操作。address是连接客户端的地址。
sk.connect(address)
  # 连接到address处的套接字。一般,address的格式为元组(hostname,port),如果连接出错,返回socket.error错误。
sk.connect_ex(address)
  # 同上,只不过会有返回值,连接成功时返回 0 ,连接失败时候返回编码。
sk.close()
  # 关闭套接字
sk.recv(bufsize[,flag])
  # 接受套接字的数据。数据以字符串形式返回,bufsize指定最多可以接收的数量。flag提供有关消息的其他信息,通常可以忽略。
sk.recvfrom(bufsize[.flag])
  # 返回值是(data,address)。其中data是包含接收数据的字符串,address是发送数据的套接字地址。
sk.send(string[,flag])
  # 将string中的数据发送到连接的套接字。返回值是要发送的字节数量,该数量可能小于string的字节大小。即:可能未将指定内容全部发送。
sk.sendall(string[,flag])
  # 将string中的数据发送到连接的套接字,但在返回之前会尝试发送所有数据。成功返回None,失败则抛出异常。内部通过循环调用send,将所有内容发送出去。
sk.sendto(string[,flag],address)
  # 将数据发送到套接字,address是形式为(ipaddr,port)的元组,指定远程地址。返回值是发送的字节数。该函数主要用于UDP协议。
sk.settimeout(timeout)
  # 设置套接字操作的超时期,timeout是一个浮点数,单位是秒。值为None表示没有超时期。
sk.getpeername()
  # 返回连接套接字的远程地址。返回值通常是元组(ipaddr,port)。
sk.getsockname()
  # 返回套接字自己的地址。通常是一个元组(ipaddr,port)
sk.fileno()
  # 套接字的文件描述符
套接字方法
import socket, os

# 创建一个INET,TCP套接字
sk = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

# 监听的地址和端口
sk.bind(('127.0.0.1', 8080))
# 开始监听,可以指定等待的最大连接数,超过则拒绝连接
sk.listen(5)

# 接受连接并返回(conn, address),conn为建立连接的套接字对象,address是客户端的地址端口
conn, address = sk.accept()

# 接受对端发送的数据,bytes类型,最大1024
header_data = conn.recv(1024)
header_data = str(header_data, 'utf8').split()
mode, file_path, file_size = header_data
file_size = int(file_size)
file_name = os.path.basename(file_path)
local_path = os.path.abspath(__file__)
local_path = os.path.dirname(local_path)
file_path = '\\'.join([local_path, file_name])
if mode == 'post':
    data_len = 0
    with open(file_path, 'wb') as f:
        while data_len < file_size:
            recv_data = conn.recv(1024)
            f.write(recv_data)
            data_len += len(recv_data)
server端
import socket, os

# 创建INET,TCP套接字
sk = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

# 发起套接字连接
sk.connect(('127.0.0.1', 8080))

request = input('>>>').split(' ')
command, file = request
file_path = os.path.abspath(file)
file_size = os.stat(file_path).st_size
file_size_str =str(file_size)
request = ' '.join([command, file_path, file_size_str])
header_data = bytes(request, encoding='utf8')
# 向建立连接的套接字,尝试发送所有数据,成功返回None,失败则抛出异常。
sk.sendall(header_data)
data_len = 0
while data_len < file_size:
    with open(file_path, 'rb') as f:
        send_data = f.read(1024)
        sk.sendall(send_data)
        data_len += len(send_data)
sk.close()
print('%s successed' % command)
client端

socketserver模块

I/O多路复用指:通过一种机制,可以监视多个描述符(socket),一旦某个描述符就绪(一般是读就绪或者写就绪),能够通知程序进行相应的读写操作。

SocketServer内部使用 IO多路复用 以及 “多线程” 和 “多进程” ,从而实现并发处理多个客户端请求的Socket服务端。即:每个客户端请求连接到服务器时,Socket服务端都会在服务器是创建一个“线程”或者“进程” 专门负责处理当前客户端的所有请求。

import socketserver

# 创建一个BaseRequestHandler继承类,重写handle方法
class MyServer(socketserver.BaseRequestHandler):

    def handle(self):
        print('start')
        while True:
            data = self.request.recv(1024)
            print(data, 'sd')
            if not data:
                break
            self.request.send(data)
            data = str(data, 'utf8')
            print(data)

# 实例化一个多线程的socket套接字对象
sk = socketserver.ThreadingTCPServer(('127.0.0.1', 8080), MyServer)
# 调用serve_forever方法,执行重写后的handle方法
sk.serve_forever()
server端
import socket

sk = socket.socket()
sk .connect(('127.0.0.1', 8080))

while True:
    data = input('>>>')
    if not data:
        break
    data = bytes(data, 'utf8')
    sk.sendall(data)
    recv_data = sk.recv(1024)
    recv_data = str(recv_data, 'utf8')
    print(recv_data)

sk.close()
client端

 

posted @ 2019-09-11 17:27  houyongchong  阅读(127)  评论(0编辑  收藏  举报