每天写一点,总有一天我这条咸鱼能变得更咸

 

文件参考:点击这里(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)
server

  客户端

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
client

 

  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)
client
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
server

一. 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()
服务端