在java中通过套接字发送大数据

时间:2010-07-06 02:29:55

标签: java c sockets networking

我正在研究客户端服务器架构,我只是初学者。这里我的服务器是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中相应的函数将捕获文件句柄。

提前谢谢。

3 个答案:

答案 0 :(得分:1)

您滥用send()/ recv()函数。由于内核中可能存在限制,send()和recv()不需要发送您请求的数据。您必须反复调用send()直到所有数据都被推送完毕。

e.g:

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;
}

答案 1 :(得分:1)

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;
    }
}

答案 2 :(得分:0)

  1. 调用m_socket = new Socket(...)后,m_socket不能为该行。它将抛出异常或将Socket分配给m_socket,永远不为null。所以这个测试毫无意义。

  2. 调用readLine()后,必须检查空返回值,这意味着EOS,这意味着另一端已关闭连接,这意味着您必须退出读取循环并关闭套接字。

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

    int count;
    byte[] buffer = new byte[8192];
    while ((count = in.read(buffer)) > 0)
        out.write(buffer, 0, count);
    
  4. 如果您的发送端在完成发送文件时没有关闭套接字,则必须让它在文件之前发送文件长度,并修改上面的循环以准确读取该字节数。