Отправка больших данных через сокеты в Java - PullRequest
1 голос
/ 06 июля 2010

Я работаю над архитектурой клиент-сервер, и я только начинающий в этой области.Здесь мой сервер на 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, pos, len)"в коде C вместо «send ()».Этот метод отправляет дескриптор файла.Так что же будет соответствующей функцией в Java для захвата дескриптора файла.

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

Ответы [ 3 ]

1 голос
/ 06 июля 2010

Вы неправильно используете функции 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 голос
/ 18 августа 2011

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;
    }
}
0 голосов
/ 06 июля 2010
  1. m_socket не может быть нулевой линией после вызова m_socket = new Socket(...).Он либо сгенерирует исключение, либо присвоит m_socket 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);
    

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...