3

I have a server in a raspberry pi, and want to allow multithreading. The server is working. The client is in windows. I believe I need to send the socket id through the pthread_create, but haven't found how. Is there anything else I need to send? What is the best way to do it?

I've searched the internet, stackoverflow included, and tryed some resolutions, but they didn't work.

const int PORT = 12000;
TCPServer tcp;
pthread_t my_thread[MAXCLIENTQUEUE];
int clientID = 0;

int main()
{

    tcp.setup(PORT);    

    int clientQueueSize = 0, threadJoin = 0;
    void *res;

    do {
        socklen_t sosize = sizeof(tcp.clientAddress);
        //realizar o accept
        tcp.newsockfd[clientQueueSize] = accept(tcp.sockfd, (struct sockaddr*) & tcp.clientAddress, &sosize);
        if (tcp.newsockfd[clientQueueSize] == -1)
        {
            cout << "Error accepting -> " << tcp.newsockfd[clientQueueSize] << endl;
            tcp.detach();
        }
        cout << ">- accept: " << strerror(errno) << " / codigo: " << tcp.newsockfd[clientQueueSize] << " - Endereco: " << inet_ntoa(tcp.clientAddress.sin_addr) << endl;
        clientID++;
        cout << ">>> client accepted" << " | Client ID: " << clientID << endl;
        // criar threads
        int ret = pthread_create(&my_thread[clientQueueSize], NULL, messenger, &tcp.newsockfd[clientQueueSize]);
        cout << ">- pthread: " << strerror(errno) << " / codigo: " << ret << endl;
        if (ret != 0) {
            cout << "Error: pthread_create() failed\n" << "thread_n " << my_thread[clientQueueSize] << endl;
            exit(EXIT_FAILURE);
        }
        cout << "thread n " << my_thread[clientQueueSize] << endl;
        clientQueueSize++;
        }
    while (clientQueueSize < MAXCLIENTQUEUE);

    pthread_exit(NULL);

    return 0;
}

The server accepts multiple connections but only sends messages to the first client, the others connected successfully, but never receive messages. I want for the server to be able to send messages to all the clients.

Rui
  • 33
  • 4

1 Answers1

1

You have to create threads for all sockets. Or, use Windows-depended async select methods.

P.S. Forget pthreads and use the standard std::thread.

   map<SOCKET,std::string> clients;
   void newclient(SOCKET x)
   {
       for(;;)
       {
       int r = recv(x,...);
       if (r == 0 || r == -1) 
           break;
       }
     // remove it from clients, ensure proper synchronization

   }

   void server()
   {
      SOCKET x = socket(...);
      bind(x,...);
      listen(x,...);
      for(;;)
       {
           auto s = accept(x,...);
           if (s == INVALID_SOCKET)
               break;

           // save to a map, for example, after ensuring sync with a mutex and a lock guard

           m[s] = "some_id";

           std::thread t(newclient,s);
           s.detach();
       }
   }

   int main() // 
   {
          // WSAStartup and other init

          std::thread t(server);
          t.detach();

          // Message Loop or other GUI

   }
Michael Chourdakis
  • 10,345
  • 3
  • 42
  • 78