【问题标题】:Sending large data over sockets in java在java中通过套接字发送大数据
【发布时间】:2011-03-12 02:54:58
【问题描述】:

我正在研究客户端服务器架构,我只是这方面的初学者。这里我的服务器是 C 的,客户端是 Java 的,我想从 C 服务器向 Java 客户端发送大小约为 10 - 20 MB 的二进制/数据库(.db)/图像文件。但是在执行以下代码时会丢失数据:

服务器端C代码为:

int sockfd, newsockfd, portno, clilen;   

struct sockaddr_in serv_addr, client_addr;

sockfd = socket(AF_INET, SOCK_STREAM, 0);
if(sockfd < 0)
{
    strcpy(message,"Error opening socket");
    eFlag = 1;
    send_message(message);
}

bzero((char *)&serv_addr, sizeof(serv_addr));
portno = 6789;
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = INADDR_ANY;
serv_addr.sin_port = htons(portno);

if(bind(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0)
{
    strcpy(message,"Error on binding");
    eFlag = 1;
    send_message(message);
}

listen(sockfd, 5);
clilen = sizeof(client_addr);
newsockfd = accept(sockfd, (struct sockaddr *)&client_addr, &clilen);

if(newsockfd < 0)
{
    strcpy(message,"Error on accept");
    eFlag = 1;
    send_message();
    exit(4);
}

void send_file()
{
    buffer = (char *)malloc(sizeof(char)*lSize);

    result = fread(buffer, sizeof(char), lSize, fp);
    printf("\n\n########## data read into buffer successfully #######");


    if(newsockfd)
    {
        n = send(newsockfd, buffer, lSize);
        printf("\n\n$$$$$$$$ Data sent successfully $$$$$");
        strcpy(message,"Data sent successfully");
        send_message(message);
    }


    else
    {
        strcpy(message, "Error writing on socket");
        send_message(message);
    }

    sleep(sleepTime);
    sleepTime = (int) (sleepTime*1.02);

    free(buffer);
}

而且,我的客户端 Java 代码是:

                    final int PORT_NO = 6789;
        final String Server_name = "192.133.133.1";
        Socket m_socket = null;
        String str;
        int ch;

    try {
        if(m_socket == null)
            m_socket = new Socket(Server_name, PORT_NO);
        if(m_socket == null)
            System.out.println("Unable to open the socket");


    DataInputStream dis = new DataInputStream(m_socket.getInputStream());
    PrintStream ps = new PrintStream(m_socket.getOutputStream());

    DataInputStream ds = new DataInputStream(System.in);

    while(true)
    {
        System.out.println("1. Synchronize");
        System.out.println("2. Exit");
        System.out.println("Enter your choice...");
        str = ds.readLine();
        ch = Integer.parseInt(str);

        switch(ch)
        {
        case 1:
     ps.println("<message action='buttonpress' value='synchronize' />");
     System.out.println("avilable data to read is:"+dis.available());
     FileOutputStream fos = new FileOutputStream("mukul.db");



            byte data[] = new byte[102400]; //100 Kb byte array

                            dis.read(data);


            String str_data = new String(data);
            str_data = str_data.trim();
            data = str_data.getBytes();

            fos.write(data);
            fos.close();

            break;

这里只读取部分数据,即大约 10 kb 或更少。

我只是此类帖子的初学者,我的代码可能很麻烦,所以请忽略发布中的所有错误。

所以请告诉我如何在这种客户端-服务器架构中接收 1 MB/10 MB 的数据而不会丢失数据。

如果我在 C 代码中使用“sendfile(out_fp, in_fp, pos, len)”方法而不是“send()”会怎样。此方法发送文件句柄。那么Java中对应的捕获文件句柄的函数是什么。

提前谢谢你。

【问题讨论】:

    标签: java c sockets networking


    【解决方案1】:
    1. 调用m_socket = new Socket(...) 后,m_socket 不可能为空。它要么抛出异常,要么将Socket 分配给m_socket,从不为空。所以那个测试是没有意义的。

    2. 调用readLine()后必须检查返回值是否为空,即EOS,表示对方已关闭连接,即必须退出读取循环并关闭socket。

    3. 正如 Javadoc 中所说,InputStream.available() 不应用于 EOS 测试。它的约定是返回可以读取的字节数没有阻塞。这与通过套接字传入文件的长度很少相同。您必须继续阅读套接字,直到 EOS:

      int count;
      byte[] buffer = new byte[8192];
      while ((count = in.read(buffer)) > 0)
          out.write(buffer, 0, count);
      

    如果您的发送端在完成发送文件时没有关闭套接字,您将不得不让它在文件之前发送文件长度,并修改上面的循环以准确读取那么多字节。

    【讨论】:

    • 谢谢你,它帮助我成功地从服务器发送数据。
    【解决方案2】:

    您误用了 send()/recv() 函数。由于内核中可能存在限制,send() 和 recv() 不需要发送您请求的数据。您必须一遍又一遍地调用 send(),直到所有数据都推送完。

    例如:

    int sent = 0;
    int rc;
    while ( sent < should_send )
    {
       rc = send(sock, buffer + sent, should_send - sent, 0);
       if ( rc <= 0 ) // Error or hangup
          // do some error handling;
    
       sent += rc;
    }
    

    【讨论】:

    • 谢谢。它有助于在客户端成功接收数据。
    【解决方案3】:

    Java端,

    int lent2 = 0;
    int LengthToReceive = 102400;
    char[] chTemp = new char[LengthToReceive];
    
    while (true) {
    
        int readlength = bufferedreader.read(chTemp, lent2,LengthToReceive - lent2);
        if(readlength==-1){
            break;
        }
    
        lent2 += readlength;
        if (lent2 >= LengthToReceive) {
            flag = false;
            break;
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-10-13
      • 2020-12-03
      • 1970-01-01
      • 2018-07-15
      • 2010-12-10
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多