Отправка больших данных по сокетам в Java

Я работаю над клиент-серверной архитектурой, и я - просто новичок в этой вещи. Здесь мой сервер имеет C, и клиент имеет Java, и я хочу отправить двоичный файл/базу данных (.db) / файл изображения размера приблизительно 10 - 20 МБ от сервера C до клиента Java. Но данные потеряны при реализации следующего кода:

Сторона сервера 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 Кбит или меньше.

Я - просто новичок к таким сообщениям, и мой код может быть громоздким, поэтому проигнорируйте все ошибки в регистрации.

Поэтому скажите мне, как я могу получить 1 МБ / 10 МБ данных в этой клиент-серверной архитектуре без потери данных.

Что, если я использую "sendfile (out_fp, in_fp, на месте продажи, len)", метод в коде C вместо "отправляет ()". Этот метод отправляет дескриптор файла. Таким образом, какова будет соответствующая функция в Java для получения дескриптора файла.

Заранее спасибо.

1
задан 2 revs, 2 users 80% 6 July 2010 в 02:35
поделиться

2 ответа

  1. m_socket не может быть обнулен в строке после вызова m_socket = new Socket (...) . Он либо вызовет исключение, либо присвоит Socket m_socket, но никогда не будет иметь значение NULL. Так что это испытание бессмысленно.

  2. После вызова readLine () вы должны проверить возвращаемое значение null, что означает EOS, что означает, что другой конец закрыл соединение, что означает, что вы должны выйти из цикла чтения и закрыть сокет. .

  3. Как сказано в документации Javadoc, InputStream.available () не следует использовать для тестирования EOS. Его контракт должен вернуть количество байтов, которые могут быть прочитаны без блокировки. Это редко совпадает с длиной файла, поступающего через сокет. Вы должны продолжать читать сокет, пока EOS:

     int count;
    байт [] буфер = новый байт [8192];
    в то время как ((count = in.read (buffer))> 0)
    out.write (буфер, 0, счетчик);
    

Если ваша отправляющая сторона не закрывает сокет, когда он заканчивает отправку файла, вам придется заставить его отправлять длину файла перед файлом и изменить цикл выше, чтобы прочитать ровно столько байтов.

0
ответ дан 2 September 2019 в 23:16
поделиться

Вы неправильно используете функции 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;
}
1
ответ дан 2 September 2019 в 23:16
поделиться
Другие вопросы по тегам:

Похожие вопросы: