Python socket上传文件的服务端和客户端实现

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进行通信。

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

终端增强工具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('\00')
            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()

在这里插入图片描述
转载:https://blog.csdn.net/luckytanggu/article/details/53491892

猜你喜欢

转载自blog.csdn.net/qq_38641985/article/details/84955619