2015-02-03 1 views
0

У меня есть простая реализация клиента c сервера и java, и я тестирую сервер для обработки запросов. Я использую службу-исполнитель для имитации одновременных запросов.Данные не получены на сервере c при использовании службы-исполнителя от java-клиента

Механизм: терминал просто считывает строку с клиента и подтверждает ее, отправив сообщение клиенту.

Ошибка: для некоторых запросов сервер не получает сообщение, отправленное клиентом.

C сервер:

#include <stdio.h> 
#include <string.h> //strlen 
#include <stdlib.h> //strlen 
#include <sys/socket.h> 
#include <arpa/inet.h> //inet_addr 
#include <unistd.h> //write 
#include <pthread.h> //for threading , link with lpthread 

//the thread function 
void *connection_handler(void *); 

int main(int argc , char *argv[]) 
{ 
    int socket_desc , client_sock , c; 
    struct sockaddr_in server , client; 
    static int client_count = 0; 

    //Create socket 
    socket_desc = socket(AF_INET , SOCK_STREAM , 0); 
    if (socket_desc == -1) 
    { 
     printf("Could not create socket"); 
    } 
    puts("Socket created"); 

    //Prepare the sockaddr_in structure 
    server.sin_family = AF_INET; 
    server.sin_addr.s_addr = INADDR_ANY; 
    server.sin_port = htons(5000); 

    //Bind 
    if(bind(socket_desc,(struct sockaddr *)&server , sizeof(server)) < 0) 
    { 
     //print the error message 
     perror("bind failed. Error"); 
     return 1; 
    } 
    puts("bind done"); 

    //Listen 
    listen(socket_desc , 1000); 

    //Accept and incoming connection 
    puts("Waiting for incoming connections..."); 
    c = sizeof(struct sockaddr_in); 
    pthread_t thread_id; 

    while((client_sock = accept(socket_desc, (struct sockaddr *)&client, (socklen_t*)&c))) 
    { 
     client_count++; 
     printf("Connection accepted for client no : %d\n",client_count); 

     if(pthread_create(&thread_id , NULL , connection_handler , (void*) &client_sock) < 0) 
     { 
      perror("could not create thread"); 
      return 1; 
     } 

     //Now join the thread , so that we dont terminate before the thread 
     //pthread_join(thread_id , NULL); 
     puts("Handler assigned"); 
    } 

    if (client_sock < 0) 
    { 
     perror("accept failed"); 
     return 1; 
    } 

    return 0; 
    } 

    void *connection_handler(void *socket_desc) 
    { 
     //Get the socket descriptor 
     int sock = *(int*)socket_desc; 
     int read_size, t = 0, operation = -1, buffer_size = 0; 
     char *message , recv_meta[2000], *data[3]; 

     //Receive a message from client 
     while(read_size = recv(sock, recv_meta, 2000, 0) > 0) { 
     printf("Meta from client : %s\n",recv_meta); 
     sprintf(recv_meta, "%s", "OK, Meta Data received!"); 
     send(sock, recv_meta, strlen(recv_meta), 0); //send acknowledgement 
    } 
    if(read_size == 0) 
    { 
     puts("Client disconnected"); 
     fflush(stdout); 
    } 
    else if(read_size == -1) 
    { 
     perror("recv failed"); 
    } 

    return 0; 
    } 

Java Client:

import java.net.*; 
import java.io.*; 
import java.util.Arrays; 
import java.util.concurrent.*; 

public class client 
{ 
    public static void main(String[] args) 
    { 
     ExecutorService executorService = Executors.newFixedThreadPool(100); 
     for (int i = 0; i < 5; i++) { 
      Runnable worker = new WorkerThread(""+i); 
      executorService.execute(worker); 
     } 
     executorService.shutdown();   
    } 
} 

class WorkerThread implements Runnable { 
    String clientcount = ""; 
    public WorkerThread(String s){ 
     this. clientcount=s; 
    } 

    @Override 
    public void run() { 
     Socket socket = null; 
     int PORT = 5000, buffer_size = 0; 
     String meta = " "; 

     meta = "newfileidforenc:1:20000"; 

     // Create the socket connection to the EchoServer. 
     try 
     { 
      socket = new Socket("localhost", PORT); 
     }   
     catch(UnknownHostException uhe) 
     { 
      // Host unreachable 
      System.out.println("Unknown Host"); 
     } 
     catch(IOException ioe) 
     { 
      // Cannot connect to port on given host 
      System.out.println("Cant connect to server at port "+PORT+". Make sure it is running."); 
      return; 
     } 
     try 
     { 
     PrintWriter pout = new PrintWriter(new OutputStreamWriter(socket.getOutputStream())); 
     BufferedReader pin = new BufferedReader(new InputStreamReader(socket.getInputStream())); 
     pout.println(meta); 
     pout.flush(); 
     System.out.println("\nServer Says : " + pin.readLine() + "for "+ clientcount); 
     } 
     catch(Exception ioe) 
     { 
      System.out.println("\nException during communication. Server probably closed connection."); 
     } 
     finally 
     { 
      try 
      { 
       // Close the socket before quitting 
       socket.close(); 
      } 
      catch(Exception e) 
      { 
       e.printStackTrace(); 
      }     
     } 
    } 
} 

Вывод: Это не то же самое. Весь клиент подключается и успешно отключается. Но сервер не получает и не печатает данные со всех клиентов.

+0

Ну, прямо, сервер игнорирует возврат «read_size» из вызова recv() после успешного чтения. Затем «printf (« Мета от клиента:% s \ n », recv_meta); пытается распечатать буфер, который не гарантируется завершением нулевого значения. –

+0

Даже если вызов recv() считывает всю строку, отправленную клиентом за один раз (что НЕ гарантировано), клиент отправляет данные, которые не имеют нулевого окончания. –

+0

'pthread_create (...., & client_sock'), передает адрес var, который является локальным для потока accept(), а не передает его по значению. –

ответ

0

Я нашел решение проблемы.

Актуальная проблема: служба Executor используется для нагрузочного тестирования, то есть будет больше количества запросов, отправленных в секунду. При такой большой нагрузке код переходит в состояние гонки. Client_sock, адрес которого передается pthread_create(), перезаписывается следующим вызовом accept(), прежде чем он будет скопирован в переменную sock внутри connection_handler(). Это приводит к сценарию, когда одно соединение будет обрабатываться двумя или более потоками, а некоторые другие соединения остаются необработанными.

Решение: Скопируйте client_sock в строковый буфер, который должен быть передан как аргумент для pthread_create().

Надеюсь, это будет полезно.

0

У вас есть многочисленные проблемы, связанные с:

1) Не правильно обработки TCP потоки и предполагая, что TCP передает сообщения вместо октет (байт) потоков.

2) Не ценим массивы символов с нулевым завершающим символом C, которые msaquerade как строковый тип.

3) Передача значений по адресам в поток создает вызовы.

Просмотреть комментарии.

+0

Спасибо за помощь. Я нашел решение проблемы. – Sudershan