线程-UDP传输文件,通过网线直连,低速传输正常,高速传输丢包的问题

问题描述

UDP传输文件,通过网线直连,低速传输正常,高速传输丢包的问题

用UDP传输视频文件,VC发送数据到安卓端,安卓端监听端口接收数据,采用网线直连,排除网络原因造成的丢包。当VC发送数据延时50ms(大概几百K每秒的速度发包),JAVA端能正确接收。可是不延时50ms发送时(大概2M/S的速度发包)JAVA端接收就出现丢包。JAVA开了两个线程,一个线程接收并放到缓冲队列,另一个线程从缓冲队列取出数据写入U盘。缓冲队列大小也比发送的文件要大,也不可能是缓冲队列不够大的问题。希望得到大神指点,代码如下:
void CSendudpDlg::OnBUTTONSendfile()
{
SOCKET sockClient=socket(AF_INET,SOCK_DGRAM,0);
SOCKADDR_IN addSrv;

CString str;
CTypeChange myChang;
unsigned char xbuf[4096];
int len;

m_portdest=8899;
m_serverIP="192.168.1.4";
HANDLE hfile;
hfile=CreateFile("D:\amy.mp4",
                GENERIC_READ,
                FILE_SHARE_READ|FILE_SHARE_WRITE,
                NULL,
                OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);

addSrv.sin_addr.S_un.S_addr = inet_addr(m_serverIP);
addSrv.sin_family   = AF_INET;
addSrv.sin_port     = htons(m_portdest);
DWORD dwstart,dwend,dwrate;
DWORD file_len=19025412;
int npack=file_len/4063;
DWORD ret,lret;
int num=0;

while(npack--)
{
    memset(&xbuf,0,sizeof(xbuf));
    ret=ReadFile(hfile,xbuf,4063,&lret,NULL);
    if( lret == 0)
    {
        SetFilePointer(hfile,0,0,FILE_BEGIN);
        continue;
    }
    xbuf[1]=4077/256; //包头信息
    xbuf[2]=4077%256;
    xbuf[3]=(num/256)/256;
    xbuf[4]=(num/256)%256;
    xbuf[7]=num%256;
    ::Sleep(50);
    sendto(sockClient,(char*)xbuf,4096,0,(SOCKADDR*)&addSrv,sizeof(SOCKADDR));
    num++;

}
cprintf("end!!!!!!!n");
closesocket(sockClient);

}

安卓端:
package com.example.util;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;
import java.util.Arrays;

import android.os.Environment;
import android.util.Log;

import com.example.net.Invoker;

/**

  • 封装了数据生产工厂,该工厂中提供了生产和消费方法
  • @author Jry
    *
    */
    public class Factory {

    private int read_loc;
    private int write_loc;
    private int buffer_len;
    private int content_len;
    private int buffers_count;
    private byte[] buffers;
    private int[] flags;

    private File file = null;
    private String filePath = null;
    private RandomAccessFile raf = null;
    private static final String CRLF = "rn";

    private DatagramSocket datagramSocket = null;
    private DatagramPacket dataPacket = null;

    private Object read_lock = new Object();
    private Object write_lock = new Object();

    private static Factory instance = null;

    private int last_pos;
    private int[][] loc_map = null;

    private Invoker invoker = null;

    public static Factory newInstance() {
    if (null == instance) {
    synchronized (Factory.class) {
    if (null == instance) {
    instance = new Factory();
    }
    }
    }
    return instance;
    }

    private Factory() {
    initialize();
    invoker = Invoker.getInstance();
    }

    private void initialize() {
    last_pos = 0;
    read_loc = 0;
    write_loc = 0;
    buffer_len = 4096;
    content_len = 4063;
    buffers_count = 1024 * 10;
    flags = new int[buffers_count];
    loc_map = new int[4063][256];
    buffers = new byte[buffer_len * buffers_count];

    Arrays.fill(flags, 0);
    for (int[] temp : loc_map) {
        Arrays.fill(temp, 0);
    }
    // 设置输出流
    filePath = Environment.getExternalStorageDirectory().getPath() + "/video/test.mp4";
    file = new File(filePath);
    if (file.exists()) {
        Log.i("123", "file has been existed !!!" + CRLF);
        if (file.delete()) {
            Log.i("123", "file has benn deleted!!!" + CRLF);
        }
    }
    try {
        if (file.createNewFile()) {
            Log.i("123", "成功创建新文件!!!" + CRLF);
        }
    } catch (IOException e2) {
        e2.printStackTrace();
    }
    
    // 预分配文件所占的磁盘空间,磁盘中会创建一个指定大小的文件
    try {
        raf = new RandomAccessFile(filePath, "rw");
        raf.setLength(19025412); // 预分配 19025412 的文件空间
        raf.close();
    } catch (FileNotFoundException e1) {
        e1.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }
    
    // 设置socket的监听端口
    try {
        datagramSocket = new DatagramSocket(8899);
        // datagramSocket.setSoTimeout(10000);
        Log.i("123", "datagramsocket start successed!!!");
    } catch (SocketException e) {
        Log.i("123", "datagramsocket start failed!!!");
        e.printStackTrace();
    }
    

    }

    //计数当前总共收到了多少个数据包
    private int j = 0;

    public void create() {
    while (flags[write_loc] == 1) {
    synchronized (read_lock) {
    try {
    read_lock.wait();
    } catch (InterruptedException e) {
    e.printStackTrace();
    }
    }
    }
    byte[] buffer = new byte[buffer_len];
    byte[] receiveByte = new byte[buffer_len];
    dataPacket = new DatagramPacket(receiveByte, buffer_len);
    try {
    datagramSocket.receive(dataPacket);
    Log.i("123", "收到了数据包 !!!" + " dataPacket.getLength() ==" + dataPacket.getLength());
    int len = dataPacket.getLength();
    if (len == buffer_len) {
    buffer = dataPacket.getData();
    System.arraycopy(buffer, 0, buffers, write_loc * buffer_len, buffer_len);
    Log.i("123", "写入缓存数据的长度------" + len + "------" + write_loc + CRLF);
    Log.i("123", "当前受到包的数据包的数量是------" + (++j) + CRLF);
    flags[write_loc] = 1;
    write_loc = (write_loc + 1) % buffers_count;
    synchronized (read_lock) {
    read_lock.notifyAll();
    }
    }
    } catch (IOException e) {
    e.printStackTrace();
    }

    }

    public void consume() {
    while (flags[read_loc] == 1) {
    try {
    raf = new RandomAccessFile(filePath, "rw");
    int start_loc = buffer_len * read_loc;
    /*
    int offset = i*buffer_len;
    raf.seek(offset);
    raf.write(buffers, start_loc, buffer_len);
    Log.i("123", "写入文件数据的长度*****************" + buffer_len +"read_loc == " + read_loc+CRLF);
    */
    int section = (buffers[start_loc + 7] & 0x0FF);
    int module = (buffers[start_loc + 3] & 0x0FF) * 256 + (buffers[start_loc + 4] & 0x0FF);
    int len = (buffers[start_loc + 1] & 0x0FF) * 256 + (buffers[start_loc + 2] & 0x0FF);
    int cur_pos = module * 256 + section;

            Log.i("123", "module == " + module + ",       section == " + section + ",    len == " + len + CRLF);
    
            if (loc_map[module][section] == 0) {
                // 补包的代码
                // if (!((last_pos + 1) == cur_pos)) {
                // int gap = cur_pos - last_pos - 1;
                // for (int i = 0; i < gap; i++) {
                // Command command = new
                // ConcreteCommand(UDPSender.getInstance());
                // command.setOrderNum(++last_pos);
                // invoker.addCommand(command);
                // }
                // invoker.executeCommand();
                // }
                loc_map[module][section] = 1;   // 表示该包号的包已经接收
                raf.seek(cur_pos * content_len);
                raf.write(buffers, start_loc + 13, len - 14);
                last_pos = cur_pos;
                Log.i("123", "写入文件数据的长度*****************" + (len - 14) + "*******" + read_loc + CRLF);
            }
            flags[read_loc] = 0;
            read_loc = (read_loc + 1) % buffers_count;
            synchronized (write_lock) {
                write_lock.notifyAll();
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                raf.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    synchronized (read_lock) {
        try {
            read_lock.wait();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
    

    }
    }

解决方案

建议你先只用一个接收线程进行测试,只接收不处理,看看速度能不能跟得上:及不丢包。如果这样都不行,说明不是你程序的问题,而可能是系统性能的原因。
如果这样不丢包,或者很少丢包,则说明是你程序的处理问题。

解决方案二:

单线程试了,不处理数据和处理数据都丢包,提问的时候忘说了。至于系统性能的问题,具体的可能原因有哪些?安卓端的CPU处理不够快?

解决方案三:

传文件为啥用udp。。本来udp就不care接收方的,为啥不用tcp。。

时间: 2024-10-31 12:10:19

线程-UDP传输文件,通过网线直连,低速传输正常,高速传输丢包的问题的相关文章

文件传输-用xmpp传输文件不成功

问题描述 用xmpp传输文件不成功 用安卓端给spark客户端传输文件,spark端能显示接受提醒,但是选择接收后无法传输文件,而安卓端的传输状态始终是negotiating transfer,直到连接超时,logcat不断提示"DSR is on. Don't send DTR on Android",请问是什么原因?

安立知一次解决高速传输测试挑战

资讯瞬息万变,我们正处于一个科技革命的世代,目睹一场世纪革新.随着即将到来的2020年东京奥运,包括5G行动网路.IoT物联网.8K超高清影像显示技术等相关基础建设都正积极佈建中,促使高速传输介面迈向新的里程. 随着巨量资料浪潮来袭,传输需求强力带动了高速介面发展.400Gb/s & PCIe Gen4 进一步联手带领 Data Center 航向新纪元,USB 3.1 Gen2 & Thunderbolt?3 军备再升级以满足高速影音传输需求,100G PON 亦应运而生.面对高速传输应

自己写了一个关于java UDP传输文件的代码,运行不了,没有错误,不知道哪里出问题了,求助!

问题描述 自己写了一个关于java UDP传输文件的代码,运行不了,没有错误,不知道哪里出问题了,求助! 发送端: import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.io.BufferedInputStream; import java.io.DataInputStream; import java.io.File; import java.io.FileInputStream

Java 使用 TCP 和 UDP 传输文件

引言 本项目的目的是实现两个应用,通过网络连接在不同的主机之间传输一个文件的功能.两个应用应该分别利用 UDP 和 TCP 协议,以具有传输至少 1 MB 文件的能力. 实现和说明 源代码 两个应用都由单个程序实现,源代码下载地址. 说明 程序使用以下命令行进行编译: javac *.java 然后使用以下两个命令行运行: Receiver: # java FileReceiver [protocol] [port] Sender: # java FileSender [protocol] [h

udp-UDP 传输文件问题????

问题描述 UDP 传输文件问题???? 怎么实现UDP传输一个文件 ?原理是什么呢 ? 最好是python 实现 解决方案 UDP是标准的网络传球协议,传输文件需要做自定义的协议哦.实现,网上有很多的代码,找找看看吧! 解决方案二: 讲文件分为固定大小的包(最后一个包除外).先将总的包数告诉对方,然后根据对方的需要传制定的包. 解决方案三: 自己定义的协议 怎么做? 难道将文件内容取出来(字节) 然后发送吗

串口传输文件 lrzsz

假设有一种开发环境,一块板子,除了串口,没有任何外部出入输出设备,没有sd卡,没有网线,这个时候如果你想跟这块板子传输交互文件,要怎么办? 根据modem所采用的文件传输协议:xmodem,ymodem,zmodem将其分类   xmodem:简单通用,传输信息单位是"包=128B",传输速度慢,适合电话线路质量差的情况下用  ymodem:由XMODEM演变来,效率可靠性高,包=128*8B:一次传输可发送或接受几个文件   zmodem:于上两种不同,已连续的数据流发送数据,效率更

局域网-java socket 网络传输文件使网络使用率最大化

问题描述 java socket 网络传输文件使网络使用率最大化 局域网传输文件,如何使网络使用率最大化,主要问题是在客户端接收数据写入磁盘时会影响传输效率,有没有好的办法解决呢? 解决方案 1)文件分片并使用多线程传输,文件传输前要预先在磁盘分配好文件所需空间 2)为了提高传输效率,客户端建立数据的内存缓冲区,针对每一个文件片的传输,客户端要启一个线程负载下载到缓冲区,再启一线程从缓冲区读数据写磁盘. 解决方案二: 多线程,边传输数据边写入文件

三星S4怎么通过WLAN传输文件给其它手机

本题以Galaxy S4 zoom SM-C101向GT-S6812I发送图片为例.   1.在GT-S6812I的待机页面下,点击[应用程序]图标.   2.点击[设定].   3.点击[WLAN].   4.点击WLAN右侧的[滑动块],绿色代表已开启,然后选择[WLAN直连].   5.GT-S6812I将会搜索可用设备.   步骤 2. 选择传送文件,两手机配对连接. 1.在Galaxy S4 zoom的待机页面下,点击[应用程序].   2.点击[相册].   3.点击[照相机]文件夹

如何在linux主机和windows主机之间传输文件

首先下载pytty,解压开发现里面有plink.exe pscp.exe psftp.exe putty.exe puttygen.exe puttytel.exe等可执行文件,如果只是想要链接主机做一些操作那么使用putty.exe就可一,具体使用可以参见上面给出的链接,要想要上传下载文件,那么需要使用pscp.exe这个文件. 下面讲解使用pscp命令在Linux和Windows之间传输文件. 通过命令行进入pscp.exe所在的文件夹,直接输入pscp会看到如下提示: PS:推荐像我一样将