Hướng dẫn python udp send file - python udp gửi tập tin

I've made this sending / receiving scripts but i corrupted file ! i have no idea why I'm getting this issue !

sender.py

#!/usr/bin/env python

from socket import *
import sys

s = socket[AF_INET,SOCK_DGRAM]
host =sys.argv[1]
port = 9999
buf =1024
addr = [host,port]

file_name=sys.argv[2]

f=open[file_name,"rb"] 
data = f.read[buf]

s.sendto[file_name,addr]
s.sendto[data,addr]
while [data]:
    if[s.sendto[data,addr]]:
        print "sending ..."
        data = f.read[buf]
s.close[]
f.close[]

receiver.py

#!/usr/bin/env python

from socket import *
import sys
import select

host="0.0.0.0"
port = 9999
s = socket[AF_INET,SOCK_DGRAM]
s.bind[[host,port]]

addr = [host,port]
buf=1024

data,addr = s.recvfrom[buf]
print "Received File:",data.strip[]
f = open[data.strip[],'wb']

data,addr = s.recvfrom[buf]
try:
    while[data]:
        f.write[data]
        s.settimeout[2]
        data,addr = s.recvfrom[buf]
except timeout:
    f.close[]
    s.close[]
    print "File Downloaded"

and this the original receiver that I've modify it [works fine 100%]

#!/usr/bin/env python

from socket import *
import sys
import select

host="0.0.0.0"
port = 9999
s = socket[AF_INET,SOCK_DGRAM]
s.bind[[host,port]]

addr = [host,port]
buf=1024

f = open["file.pdf",'wb']

data,addr = s.recvfrom[buf]
try:
    while[data]:
        f.write[data]
        s.settimeout[2]
        data,addr = s.recvfrom[buf]
except timeout:
    f.close[]
    s.close[]
    print "File Donwloaded"

as you notice it's making file at the beginning.

exacted: client => send file [name.ext] => server:save it [name.ext]

my output : corrupted file for pdf and empty for txt

Nội dung chính

  • Kiến thức cần nhớ
  • UDP transfer file example
    • Cách giải bài toán
    • Cài đặt phía server
    • Cài đặt phía client
  • Download Source Code

Kiến thức cần nhớ

  • UDP có cơ chế gửi tin không tin cậy, có nghĩa là chỉ cần gửi không cần check xem đã đến đích hay chưa.
  • Trong java, cả UDP server và UDP client đều sử dụng đối tượng java.net.DatagramSocket để giao tiếp với nhau. java.net.DatagramSocket để giao tiếp với nhau.
  • Đối tượng java.net.DatagramPacket được sử dụng để đóng gói dữ liệu để gửi đi, và nhận dữ liệu dưới dạng được đóng gói. Số lượng maximum bytes bạn có thể gửi thông qua UDP là 65508 bytes cho một lần.java.net.DatagramPacket được sử dụng để đóng gói dữ liệu để gửi đi, và nhận dữ liệu dưới dạng được đóng gói. Số lượng maximum bytes bạn có thể gửi thông qua UDP là 65508 bytes cho một lần.

Đây là một ví dụ về việc sử dụng giao thức UDP để truyền file.

Cách giải bài toán

Các file được transfer có thể có dung lượng [bytes] khác nhau, đối với UDP mỗi lần transfer, số maximum bytes là 65508, do vậy chúng ta cần chia nhỏ file thành nhiều phần để gửi đi. Trước khi gửi file từ client lên server, client phải thông báo cho server biết rằng đang chuẩn bị gửi file với các thông tin như tên file, file được chia ra thành bao nhiêu phần, mỗi phần có dung lượng là bao nhiêu... các thông tin này được đóng gói trong đối tượng FileInfo. Trong ví dụ này chúng tôi chia file ra thành các phần có dung lượng 32k, và phần cuối cùng có dung lượng là phần dư của tổng dung lượng chia cho 32k. 65508, do vậy chúng ta cần chia nhỏ file thành nhiều phần để gửi đi. Trước khi gửi file từ client lên server, client phải thông báo cho server biết rằng đang chuẩn bị gửi file với các thông tin như tên file, file được chia ra thành bao nhiêu phần, mỗi phần có dung lượng là bao nhiêu... các thông tin này được đóng gói trong đối tượng FileInfo. Trong ví dụ này chúng tôi chia file ra thành các phần có dung lượng 32k, và phần cuối cùng có dung lượng là phần dư của tổng dung lượng chia cho 32k.

Cài đặt phía server

Cấu trúc project:

Tạo lớp vn.viettuts.common.FileInfo để nhận thông tin của file:

package vn.viettuts.common;

import java.io.Serializable;

public class FileInfo implements Serializable {
    private static final long serialVersionUID = 1L;

    private String destinationDirectory;
    private String sourceDirectory;
    private String filename;
    private long fileSize;
    private int piecesOfFile;
    private int lastByteLength;
    private String status;
    
    // Constructors
    
    // Getter and setter
}

Tạo lớp UDPServer.java

Tạo lớp UDPServer.java với các nội dung sau:

Định nghĩa dung lượng [32KB] mỗi lần nhận, đối tượng DatagramSocket, và port giao tiếp:

private static final int PIECES_OF_FILE_SIZE = 1024 * 32;
private DatagramSocket serverSocket;
private int port = 6677;

Phương thức openServer[]:

private void openServer[] {
    try {
        serverSocket = new DatagramSocket[port];
        System.out.println["Server is opened on port " + port];
        listening[];
    } catch [SocketException e] {
        e.printStackTrace[];
    }
}

Xử lý nhận thông tin file, và nội dung file:

public void receiveFile[] {
    byte[] receiveData = new byte[PIECES_OF_FILE_SIZE];
    DatagramPacket receivePacket;
    
    try {
        // get file info
        receivePacket = new DatagramPacket[receiveData, receiveData.length];
        serverSocket.receive[receivePacket];
        InetAddress inetAddress = receivePacket.getAddress[];
        ByteArrayInputStream bais = new ByteArrayInputStream[
                receivePacket.getData[]];
        ObjectInputStream ois = new ObjectInputStream[bais];
        FileInfo fileInfo = [FileInfo] ois.readObject[];
        // show file info
        if [fileInfo != null] {
            System.out.println["File name: " + fileInfo.getFilename[]];
            System.out.println["File size: " + fileInfo.getFileSize[]];
            System.out.println["Pieces of file: " + fileInfo.getPiecesOfFile[]];
            System.out.println["Last bytes length: "+ fileInfo.getLastByteLength[]];
        }
        // get file content
        System.out.println["Receiving file..."];
        File fileReceive = new File[fileInfo.getDestinationDirectory[] 
                + fileInfo.getFilename[]];
        BufferedOutputStream bos = new BufferedOutputStream[
                new FileOutputStream[fileReceive]];
        // write pieces of file
        for [int i = 0; i < [fileInfo.getPiecesOfFile[] - 1]; i++] {
            receivePacket = new DatagramPacket[receiveData, receiveData.length, 
                    inetAddress, port];
            serverSocket.receive[receivePacket];
            bos.write[receiveData, 0, PIECES_OF_FILE_SIZE];
        }
        // write last bytes of file
        receivePacket = new DatagramPacket[receiveData, receiveData.length, 
                inetAddress, port];
        serverSocket.receive[receivePacket];
        bos.write[receiveData, 0, fileInfo.getLastByteLength[]];
        bos.flush[];
        System.out.println["Done!"];

        // close stream
        bos.close[];
    } catch [IOException e] {
        e.printStackTrace[];
    } catch [ClassNotFoundException e] {
        e.printStackTrace[];
    }
}

Hàm main[]:

public static void main[String[] args] {
    UDPServer udpServer = new UDPServer[];
    udpServer.openServer[];
}

Download Source Code

Cấu trúc project:

Tạo lớp vn.viettuts.common.FileInfo để nhận thông tin của file:

package vn.viettuts.common;

import java.io.Serializable;

public class FileInfo implements Serializable {
    private static final long serialVersionUID = 1L;

    private String destinationDirectory;
    private String sourceDirectory;
    private String filename;
    private long fileSize;
    private int piecesOfFile;
    private int lastByteLength;
    private String status;
    
    // Constructors
    
    // Getter and setter
}

Tạo lớp UDPServer.java

Tạo lớp UDPServer.java với các nội dung sau:

Định nghĩa dung lượng [32KB] mỗi lần nhận, đối tượng DatagramSocket, và port giao tiếp:

private static final int PIECES_OF_FILE_SIZE = 1024 * 32;
private DatagramSocket clientSocket;
private int serverPort = 6677;
private String serverHost = "localhost";

Định nghĩa phương thức kết nối server connectServer[]:

#!/usr/bin/env python

from socket import *
import sys
import select

host="0.0.0.0"
port = 9999
s = socket[AF_INET,SOCK_DGRAM]
s.bind[[host,port]]

addr = [host,port]
buf=1024

data,addr = s.recvfrom[buf]
print "Received File:",data.strip[]
f = open[data.strip[],'wb']

data,addr = s.recvfrom[buf]
try:
    while[data]:
        f.write[data]
        s.settimeout[2]
        data,addr = s.recvfrom[buf]
except timeout:
    f.close[]
    s.close[]
    print "File Downloaded"
0

Xử lý gửi thông tin file và nội dung file, phương thức sendFile[]:

#!/usr/bin/env python

from socket import *
import sys
import select

host="0.0.0.0"
port = 9999
s = socket[AF_INET,SOCK_DGRAM]
s.bind[[host,port]]

addr = [host,port]
buf=1024

data,addr = s.recvfrom[buf]
print "Received File:",data.strip[]
f = open[data.strip[],'wb']

data,addr = s.recvfrom[buf]
try:
    while[data]:
        f.write[data]
        s.settimeout[2]
        data,addr = s.recvfrom[buf]
except timeout:
    f.close[]
    s.close[]
    print "File Downloaded"
1

Hàm waitMillisecond[]: đây là chỉ biện pháp tạm thời để đảm bảo gói tin đã được nhận. tạm thời để đảm bảo gói tin đã được nhận.

#!/usr/bin/env python

from socket import *
import sys
import select

host="0.0.0.0"
port = 9999
s = socket[AF_INET,SOCK_DGRAM]
s.bind[[host,port]]

addr = [host,port]
buf=1024

data,addr = s.recvfrom[buf]
print "Received File:",data.strip[]
f = open[data.strip[],'wb']

data,addr = s.recvfrom[buf]
try:
    while[data]:
        f.write[data]
        s.settimeout[2]
        data,addr = s.recvfrom[buf]
except timeout:
    f.close[]
    s.close[]
    print "File Downloaded"
2

Hàm main[]:

#!/usr/bin/env python

from socket import *
import sys
import select

host="0.0.0.0"
port = 9999
s = socket[AF_INET,SOCK_DGRAM]
s.bind[[host,port]]

addr = [host,port]
buf=1024

data,addr = s.recvfrom[buf]
print "Received File:",data.strip[]
f = open[data.strip[],'wb']

data,addr = s.recvfrom[buf]
try:
    while[data]:
        f.write[data]
        s.settimeout[2]
        data,addr = s.recvfrom[buf]
except timeout:
    f.close[]
    s.close[]
    print "File Downloaded"
3

Download Source Code

Bài Viết Liên Quan

Chủ Đề