Day09 socket,socketserver模块学习

Socket 网络编程

Python提供了两个基本的 socket 模块。Socket 和SocketServer

Sockekt

客户端:

import socket

ip_port = ('127.0.0.1', 9999)

c = socket.socket()

c.connect(ip_port) # 此处必须是以元组方式指定服务器IP及PORT

c.send(bytes(send_data, encoding='utf8')) #发送的数据必须是
字节

c.recv(1024) #接受TCP套接字的数据, Python3中发送的数据是字节,所以通信接收方的也是字节数据

c.close() #关闭套接字

服务端:

import socket

ip_port = ('127.0.0.1', 9999)

s = socket.socket() 

s.bind(ip_port) #将套接字绑定到地址,同客户端,必须元组形式

s.listen(1) #挂起的连接数为1,监听tcp连接

conn, addr = s.accept()  #接受TCP连接并返回(conn,address),其中conn是新的套接字对象,可以用来接收和发送数据。address是连接客户端的地址。

s.recv(1024)

s.send()  #发送TCP数据。将string中的数据发送到连接的套接字。返回值是要发送的字节数量,该数量可能小于string的字节大小。还有一种方法,s.sendall()  完整发送TCP数据。将string中的数据发送到连接的套接字,但在返回之前会尝试发送所有数据。成功返回None,失败则抛出异常。

s.close()

需要注意的几点:
1.基于python3.5.2版本的socket只能收发字节(python2.7可以发送str)
2.s.accept()和s.recv()是阻塞的(基于链接正常)对于s.recv(),接受的字节为空会阻塞
3.listen(n) n代表:能挂起的链接数,如果n=1,代表可以链接一个,挂起一个,第三个拒绝

解决粘包问题:
发送一个确认消息,对端接收消息,if判断接收消息的字符串是对端发出的字符串,接收数据

服务器和客户端整个交互的过程就是一来一回循环进行。

SocketServer

SokcetServer可以用来实现客户端与服务器并发连接非阻塞socket

基于socketserver的一个上传文件的实例,直接看代码:

服务端:

#!/usr/bin/env python
# -*- coding:utf-8 -*-

import socketserver,json
# 自定义一个类,继承socketserver.BaseRequestHandler
class MyServer(socketserver.BaseRequestHandler):
	# 很重要的handle方法, 必须定义!
    def handle(self):
        self.request.sendall(bytes('欢迎致电 10086,请输入1xxx,0转人工服务.',encoding="utf-8"))
        while True:
            data = self.request.recv(1024)
            if len(data) == 0:break
            print("data", data)
            print("[%s] says:%s" % (self.client_address,data.decode() ))

            task_data = json.loads( data.decode()  )
            task_action = task_data.get("action")
			# hasattr 反射,判断对象中是否存在字符串名的方法
            if hasattr(self, "task_%s"%task_action):
				#getattr 反射,调用对象中字符串名的方法
               func = getattr(self,"task_%s" %task_action)
               func(task_data) 		
            else:
               print("task action is not supported",task_action)

    def task_put(self,*args,**kwargs):
        print("---put",args,kwargs)         
        filename = args[0].get('filename')
        filesize = args[0].get('file_size')
        # 解决粘包问题
        server_response = {"status":200}
        self.request.send(bytes( json.dumps(server_response), encoding='utf-8'  ))
        f = open(filename,'wb')
        recv_size = 0
        while recv_size < filesize:
            data = self.request.recv(4096)
            f.write(data)
            recv_size += len(data)
            print('filesize: %s  recvsize:%s' % (filesize,recv_size))
        print("file recv success")
        f.close()

if __name__ == '__main__':
	# socketserver的多进程非阻塞启动
    server = socketserver.ThreadingTCPServer(('0.0.0.0',8009),MyServer)
    server.serve_forever()

客户端:

import socket
import os ,json
ip_port=('192.168.11.150',8009)

s=socket.socket()

s.connect(ip_port)

welcome_msg = s.recv(1024)
print("from server:",welcome_msg.decode())
while True:
    send_data=input(">>: ").strip()
    if len(send_data) == 0:continue

    cmd_list = send_data.split()
    if len(cmd_list) <2:continue
    task_type = cmd_list[0]
    if task_type == 'put':
        abs_filepath = cmd_list[1]
        if os.path.isfile(abs_filepath):
            file_size = os.stat(abs_filepath).st_size
            filename = abs_filepath.split("\\")[-1]
            print('file:%s size:%s' %(abs_filepath,file_size))
            msg_data = {"action":"put",
                        "filename":filename,
                        "file_size":file_size}
            s.send(  bytes(json.dumps(msg_data),encoding="utf-8"))
            # 解决粘包问题
            server_confirmation_msg = s.recv(1024)
            confirm_data = json.loads(server_confirmation_msg.decode())
            if confirm_data['status'] ==200:
                print("start sending file ",filename)
                f = open(abs_filepath,'rb')
                for line in f:
                    s.send(line)
                print("send file done ")	
        else:
            print("\033[31;1mfile [%s] is not exist\033[0m" % abs_filepath)
            continue
    else:
        print("doesn't support task type",task_type)
        continue

    recv_data=s.recv(1024)
    print(str(recv_data,encoding='utf8'))

s.close()
posted @ 2016-07-09 07:55  摸个鱼儿  阅读(208)  评论(0编辑  收藏  举报