每天写一点,总有一天我这条咸鱼能变得更咸
文件参考:点击这里(http://www.cnblogs.com/aylin/p/5572104.html)
主要内容:
1.socket
2.socketserver
一. socket
socket简介
socket起源与Unix,而Unix/Linux基本哲学之一就是"一切皆文件",对于文件用【打开】【读写】【关闭】模式来操作,socket的实现模式也是如此,可以看成是一种特殊的文件模式,创建连接,发送消息,关闭连接,其具体过程如下图所示:
代码实例如下:
服务端

import socket port = 8888 host = "127.0.0.1" #创建套接字描述字符 sk = socket.socket() #命名套接字 sk.bind((host,port)) #监听客户端的请求 sk.listen(5) while True: #等待客户端连接,阻塞过程 conn,address = sk.accept() #给予客户端响应 conn.send("welcom!!!!!\n") while True: #接收客户端消息 content = conn.recv(1024) if content == "exit": break else: data = raw_input("please input:") #回应消息给客户端 conn.send(data)
客户端

import socket host = "127.0.0.1" port = 8888 #创建套接字符描述 cl = socket.socket() #连接服务端 cl.connect((host,port)) while True: #接收服务端响应 content = cl.recv(1024) flag = 1 while flag: data = raw_input("please input:") # 发送消息到服务端 cl.send(data) if data == "exit": flag = 0 else: content = cl.recv(1024) #关闭连接 cl.close() break
server一些常用的函数
sk.bind(address)
将套接字绑定到地址,地址需要以元组的形式传入
sk.listen(n)
监听地址,n指可以挂起的最大连接数量,n的最大值为5
sk.accpet()
接受客户端连接请求并返回(conn,address),其中conn是新的套接字对象,可用来与客户端之间交互。address是客户端的地址,该步骤是阻塞的,会一直等待接收到客户端的连接请求
sk.close()
关闭连接
sk.connect(address)
连接到address处的套接字,address的格式为元组,连接出错则抛出socket异常
sk.connect_ex(address)
同上,只是连接错误返回编码
sk.recv(bufsize)
接受套接字的数据。数据以字符串形式返回,bufsize指定最多可以接收的数量
sk.recvfrom(bufsize)
与recv()类似,但是返回值为元组(data,address)
sk.send(string)
发送数据,返回值为已发送数据的长度,可能小于string的长度
sk.sendall(string)
发送数据,所有数据全部发送则返回None,发送失败则抛出异常
sk.sendto(string,address)
向指定的地址发送数据
sk.settimeout(timeout)
设置套接字操作的超时期,单位为s,类型为浮点型
关于socket的简单的实例
TCP文件上传:

import socket import sys import os ip_port = ('127.0.0.1', 8888) sk = socket.socket() sk.connect(ip_port) container = {'key': '', 'data': ''} while True: input = raw_input('path:') cmd, path = input.split('|') file_name = os.path.basename(path) file_size = os.stat(path).st_size sk.send(cmd + "|" + file_name + '|' + str(file_size)) send_size = 0 f = file(path, 'rb') Flag = True while Flag: if send_size + 1024 > file_size: data = f.read(file_size - send_size) Flag = False else: data = f.read(1024) send_size += 1024 sk.send(data) f.close() sk.close()

import socket def recv_data(): port = 8888 host = "127.0.0.1" # 创建套接字描述字符 sk = socket.socket() # 命名套接字 sk.bind((host, port)) # 监听客户端的请求 sk.listen(5) conn, address = sk.accept() while True: pre_data = conn.recv(1024) # 获取请求方法、文件名、文件大小 cmd, file_name, file_size = pre_data.split('|') # 已经接收文件的大小 recv_size = 0 # 上传文件路径拼接 f = file("b.txt", 'wb') Flag = True while Flag: # 未上传完毕, if int(file_size) > recv_size: # 最多接收1024,可能接收的小于1024 data = conn.recv(1024) recv_size += len(data) # 上传完毕,则退出循环 else: recv_size = 0 Flag = False continue # 写入文件 f.write(data) print 'upload successed.' f.close() if __name__ == "__main__": recv_data()
UDP:

import socket address = ("127.0.0.1",8880) cl = socket.socket(socket.AF_INET,socket.SOCK_DGRAM,0) while True: data = raw_input("input:") if data == "exit": break cl.sendto(data,address)

import socket address=("127.0.0.1",8880) sk = socket.socket(socket.AF_INET,socket.SOCK_DGRAM,0) sk.bind(address) while True: data = sk.recv(1024) print data
一. socketserver
socket的局限在于接收数据的过程是阻塞的,也就是说socket模块之间的通信是一对一的,举个例子来说,就像你打电话给给A的同时,A正在和B通话,你只有等待AB通话结束了,才能与A建立连接,这样显然是无法满足服务端的需求,但是socketserver确可以满足以上的需求
流程图大概如下:
socketserver 就是能处理多个客户端请求的Socket服务端。因为每个客户端请求过来的时候,服务端会创建一个线程,通过这个线程与客户端进行通信
实例如下:

import socket obj = socket.socket() obj.connect(("127.0.0.1",8080)) ret_bytes = obj.recv(1024) ret_str = str(ret_bytes) print(ret_str) while True: inp = raw_input("你好请问您有什么问题? \n >>>") if inp == "exit": obj.sendall(bytes(inp)) break else: obj.sendall(bytes(inp)) ret_bytes = obj.recv(1024) ret_str = str(ret_bytes) print(ret_str)

import socketserver class Myserver(socketserver.BaseRequestHandler): def handle(self): conn = self.request conn.sendall("你好,我是机器人") while True: ret_bytes = conn.recv(1024) if ret_bytes == "exit": break conn.sendall("你好我好大家好") if __name__ == "__main__": server = socketserver.ThreadingTCPServer(("127.0.0.1",8080),Myserver) server.serve_forever()