使用来自 java 客户端的执行程序服务时,c 服务器未收到数据

Data not received in c server while using executor service from a java client

我有一个简单的 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 客户:

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

输出:不一样。所有客户端都成功连接和断开连接。但是服务器并没有接收和打印来自所有客户端的数据。

你有很多问题:

1) 未正确处理 TCP 流并假设 TCP 传输消息而不是八位字节(字节)流。

2) 不欣赏将 msaquerade 作为字符串类型的 C 风格空终止字符数组。

3) 通过地址将值传递给线程创建调用。

查看评论。

我找到了问题的解决方案。

实际问题:Executor 服务用于负载测试,即每秒发送的请求数会更多。在如此重的负载下,代码进入竞争状态。地址被传递给 pthread_create() 的 client_sock 在被复制到 connection_handler() 内的 sock 变量之前被下一个 accept() 调用覆盖。这会导致单个连接将由两个或多个线程处理而其他一些连接未处理的情况。

解决方案:将 client_sock 复制到一个字符串缓冲区,该缓冲区应作为 pthread_create() 的参数传递。

希望有用。