2010-07-06 3 views
1

Я работаю над архитектурой клиентского сервера, и я просто начинаю эту штуку. Здесь мой сервер имеет C, а клиент - Java, и я хочу отправить файл с двоичным/базами данных (.db)/image размером около 10-20 МБ с сервера C на клиент Java. Но данные были потеряны при выполнении следующего кода:Отправка больших данных через сокеты в 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 для захвата дескриптора файла.

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

ответ

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

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

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

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

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

+0

Спасибо, это помогло мне в отправке данных с сервера успешно. – user268758

1

Вы неправильно используете функции 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; 
} 
+0

Спасибо. это помогло успешно получать данные на клиенте. – user268758

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; 
    } 
} 
Смежные вопросы