zoukankan      html  css  js  c++  java
  • socket发送文字、图片、文件---基于python实现

    socket官方文档:https://docs.python.org/2/library/socket.html

    socket中文详细介绍:http://blog.csdn.net/rebelqsp/article/details/22109925

    查看某端口是否被占用(如6666端口):sudo netstat -nap | grep 6666 如果没有查找到6666端口则说明没有被占用(额,有点废话了~~)

    客户端

    • 创建 socket
    • 连接到远程服务器
    • 发送数据
    • 接收数据
    • 关闭 socket
    #!/usr/bin/env python
    # -*- coding=utf-8 -*-
    
    
    """
    file: client.py
    socket client
    """
    
    import socket
    import sys
    
    
    def socket_client():
        try:
            s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            s.connect(('127.0.0.1', 6666))
        except socket.error as msg:
            print msg
            sys.exit(1)
        print s.recv(1024)
        while 1:
            data = raw_input('please input work: ')
            s.send(data)
            print s.recv(1024)
            if data == 'exit':
                break
        s.close()
    
    
    if __name__ == '__main__':
        socket_client()
    

    服务器端

    • 打开 socket
    • 绑定到特定的地址以及端口上
    • 监听连接
    • 建立连接
    • 接收/发送数据
    #!/usr/bin/env python
    # -*- coding=utf-8 -*-
    
    
    """
    file: service.py
    socket service
    """
    
    
    import socket
    import threading
    import time
    import sys
    
    
    def socket_service():
        try:
            s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            # 防止socket server重启后端口被占用(socket.error: [Errno 98] Address already in use)
            s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
            s.bind(('127.0.0.1', 6666))
            s.listen(10)
        except socket.error as msg:
            print msg
            sys.exit(1)
        print 'Waiting connection...'
    
        while 1:
            conn, addr = s.accept()
            t = threading.Thread(target=deal_data, args=(conn, addr))
            t.start()
    
    def deal_data(conn, addr):
        print 'Accept new connection from {0}'.format(addr)
        conn.send('Hi, Welcome to the server!')
        while 1:
            data = conn.recv(1024)
            print '{0} client send data is {1}'.format(addr, data)
            #time.sleep(1)
            if data == 'exit' or not data:
                print '{0} connection close'.format(addr)
                conn.send('Connection closed!')
                break
            conn.send('Hello, {0}'.format(data))
        conn.close()
    
    
    if __name__ == '__main__':
        socket_service()
    

    copy以上两个脚本代码后,如果你想在本地测试,直接运行这两个脚本便是(注:先运行服务端service.py脚本),下图左边是运行服务端脚本,右边打开两个终端与服务端socket进行通信。

    socket

    一屏开多个终端是不是很屌(强烈建议安装此工具,非常方便好用)

    终端增强工具Terminator 
    sudo apt-get install terminator # Ubuntu 
    yum -y install terminator # Centos

    如果你想在两台不同机器上测试,把service.py脚本上传到服务器(假设服务器ip是:192.168.1.2),然后把client.py连接ip改为:192.168.1.2,service.py监听的ip改为:192.168.1.2,接着运行这两个脚本即可

    # client.py
    s.connect(('192.168.1.2', 6666))
    
    # service.py
    s.bind(('192.168.1.2', 6666))

    利用socket进行文件、图片等传输

    传输文件主要分以下两步:

    • 将要传输的文件的基本信息发送到接收端(文件名、大小等其他信息)
    • 发送端读取文件内容并发送过去,接受端将缓存里面的内容写入文件

    注:以下发送文件代码参考:http://www.mamicode.com/info-detail-1346172.html

    发送端代码

    #!/usr/bin/env python
    # -*- coding=utf-8 -*-
    
    
    """
    file: send.py
    socket client
    """
    
    import socket
    import os
    import sys
    import struct
    
    
    def socket_client():
        try:
            s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            s.connect(('127.0.0.1', 6666))
        except socket.error as msg:
            print msg
            sys.exit(1)
    
        print s.recv(1024)
    
        while 1:
            filepath = raw_input('please input file path: ')
            if os.path.isfile(filepath):
                # 定义定义文件信息。128s表示文件名为128bytes长,l表示一个int或log文件类型,在此为文件大小
                fileinfo_size = struct.calcsize('128sl')
                # 定义文件头信息,包含文件名和文件大小
                fhead = struct.pack('128sl', os.path.basename(filepath),
                                    os.stat(filepath).st_size)
                s.send(fhead)
                print 'client filepath: {0}'.format(filepath)
    
                fp = open(filepath, 'rb')
                while 1:
                    data = fp.read(1024)
                    if not data:
                        print '{0} file send over...'.format(filepath)
                        break
                    s.send(data)
            s.close()
            break
    
    
    if __name__ == '__main__':
        socket_client()
    

    接收端代码

    #!/usr/bin/env python
    # -*- coding=utf-8 -*-
    
    
    """
    file: recv.py
    socket service
    """
    
    
    import socket
    import threading
    import time
    import sys
    import os
    import struct
    
    
    def socket_service():
        try:
            s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
            s.bind(('127.0.0.1', 6666))
            s.listen(10)
        except socket.error as msg:
            print msg
            sys.exit(1)
        print 'Waiting connection...'
    
        while 1:
            conn, addr = s.accept()
            t = threading.Thread(target=deal_data, args=(conn, addr))
            t.start()
    
    def deal_data(conn, addr):
        print 'Accept new connection from {0}'.format(addr)
        #conn.settimeout(500)
        conn.send('Hi, Welcome to the server!')
    
        while 1:
            fileinfo_size = struct.calcsize('128sl')
            buf = conn.recv(fileinfo_size)
            if buf:
                filename, filesize = struct.unpack('128sl', buf)
                fn = filename.strip('0')
                new_filename = os.path.join('./', 'new_' + fn)
                print 'file new name is {0}, filesize if {1}'.format(new_filename,
                                                                     filesize)
    
                recvd_size = 0  # 定义已接收文件的大小
                fp = open(new_filename, 'wb')
                print 'start receiving...'
    
                while not recvd_size == filesize:
                    if filesize - recvd_size > 1024:
                        data = conn.recv(1024)
                        recvd_size += len(data)
                    else:
                        data = conn.recv(filesize - recvd_size)
                        recvd_size = filesize
                    fp.write(data)
                fp.close()
                print 'end receive...'
            conn.close()
            break
    
    
    if __name__ == '__main__':
        socket_service()

    打开两个终端,分别运行recv.pysend.py脚本,输入待传输文件的全路径和文件名(如:/home/test.txt),你就会在recv.py脚本路径下看到刚输入的传输文件,且文件名为new_****

  • 相关阅读:
    聊天界面的实现
    继续,迫不及待想学数据库
    今天休息,我来研究上次的代码了
    项目导入
    命令行常用的一下命令
    svn的安装和基本操作,及常见问题
    maven项目里写测试
    Eclipse里新建maven项目
    maven简介
    重装win7,没有管理员权限,没有以管理员身份运行
  • 原文地址:https://www.cnblogs.com/VseYoung/p/socket_1.html
Copyright © 2011-2022 走看看