zoukankan      html  css  js  c++  java
  • python socket编程

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

    文件参考:点击这里(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!!!!!
    ")
        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("你好请问您有什么问题? 
     >>>")
        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()
    服务端
  • 相关阅读:
    java中传值与传引用
    microsofr visual studio编写c语言
    openfile学习笔记
    在 Windows 和 Linux(Gnome) 环境下 从命令界面打开网页的方式
    使用vsphere client 克隆虚拟机
    route命令
    linux rpm问题:怎样查看rpm安装包的安装路径
    【leetcode】415. 字符串相加
    【leetcode】面试题 17.01. 不用加号的加法
    【leetcode】989. 数组形式的整数加法
  • 原文地址:https://www.cnblogs.com/gj5379/p/7743450.html
Copyright © 2011-2022 走看看