1. 程式人生 > >Python socket上傳檔案的服務端和客戶端實現

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