多个客户端套接字到单个服务器C ++

时间:2016-07-11 00:58:57

标签: c++ multithreading sockets

基本上我想要做的是使用C ++中的套接字将多线程客户端之间的消息交换到单个线程协调器。客户端将要求授予访问文件的授权权限,协调器将把它们放入队列中,一次授予一个。我认为这不是最好的解决方案,但我考虑在端口2000中为协调器创建一个套接字,以便客户端在那里发送所有消息。每个客户端都将使用其标识符(端口2001,2002,2003 ......)创建一个套接字,以便协调器可以在需要时通过这些端口回答它们。我遇到的问题是客户端停留在自己的套接字的accept()函数中,即使是第一个由协调器授予的函数。这是我下面的代码(cout“我在这里”从未在客户端显示,这就是它被卡住的地方 - 第53行):

coordinator.cpp:

#include <iostream>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>

using namespace std;

int main (int argc, char** argv) {

    const int REQUEST = 1;
    const int GRANT = 2;
    const int RELEASE = 3;
    const char* portno = "2000";
    int queue[128] = {0};
    int last = 0;

    int socket_receive, newsocket_receive, socket_send, port_send;
    string msg, msg_send;

    char buffer[256];
    memset(buffer, '|', 256);
    struct addrinfo hints, *res;
    struct addrinfo hints_send, *res_send;
    struct sockaddr_in client_address;

    bzero((char*) &hints, sizeof(hints));

    hints.ai_family = AF_INET;
    hints.ai_socktype = SOCK_STREAM;
    hints.ai_flags = AI_PASSIVE;

    getaddrinfo(NULL,portno,&hints,&res);
    socket_receive = socket(res->ai_family,res->ai_socktype,res->ai_protocol);
    bind(socket_receive, res->ai_addr, res->ai_addrlen);
    listen(socket_receive,5);
    socklen_t client_lenght = sizeof(client_address);

    while (1){
        newsocket_receive = accept(socket_receive,(struct sockaddr*)&client_address,&client_lenght);

        int n = recv(newsocket_receive,buffer,sizeof(buffer),0);
        msg.append(buffer, buffer+n);

        copy(buffer+n, buffer+256, buffer);
        char subarray[n];
        memset(subarray, '|', n);
        copy(subarray, subarray+n, buffer+256-n);

        int elems[2];
        int i = 0;
        while (i < sizeof(msg)-1){
            if (msg[i] == ':'){
                break;
            }
            i++;
        }
        if (i < 4){
            const char* char_msg0 = msg.substr(0,i).c_str();
            const char* char_msg1 = msg.substr(i+1,sizeof(msg)).c_str();
            elems[0] = atoi(char_msg0);
            elems[1] = atoi(char_msg1);

            if (elems[1] == REQUEST){
                if (last == 0){

                    port_send = 2000 + elems[0];
                    string str_port_send = to_string(port_send);
                    char const* char_port_send = str_port_send.c_str();

                    getaddrinfo("localhost",char_port_send,&hints_send,&res_send);
                    socket_send = socket(res_send->ai_family,res_send->ai_socktype,res_send->ai_protocol);
                    connect(socket_send,res_send->ai_addr,res_send->ai_addrlen);
                    msg_send = to_string(GRANT);
                    cout << "Coordinator: sending GRANT message to consumer " << elems[0] << endl;
                    send(socket_send, msg_send.data(),msg_send.size(),0);
                    close(socket_send);

                    queue[last] = elems[0];
                    last++;
                }
                else {
                    queue[last] = elems[0];
                    last++;
                }
            }
            else if (elems[1] == RELEASE){
                //SHIFT QUEUE
                last--;
            }
            msg = "";
        }
     }

    close(socket_receive);

    return 0;
}

client.cpp:

#include <iostream>
#include <pthread.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <algorithm>

using namespace std;

void *request (void *arg){

    const int REQUEST = 1;
    const int GRANT = 2;
    const int RELEASE = 3;

    int id = *((int *) arg);

    string msg_send, msg_receive;
    const char* portno = "2000";
    const char* port_receive = to_string(2000+id).c_str();
    int socket_send, socket_receive, newsocket_receive;
    char buffer [256];
    struct addrinfo hints, *res;
    struct addrinfo hints_receive, *res_receive;
    struct sockaddr_in client_address;


    bzero((char*) &hints, sizeof(hints));

    hints.ai_family = AF_INET;
    hints.ai_socktype = SOCK_STREAM;
    hints.ai_flags = AI_PASSIVE;

    getaddrinfo("localhost",portno,&hints,&res);
    socket_send = socket(res->ai_family,res->ai_socktype,res->ai_protocol);
    connect(socket_send,res->ai_addr,res->ai_addrlen);
    msg_send = to_string(id) + ":" + to_string(REQUEST);
    cout << "Client: sending REQUEST message to coordinator." << endl;
    send(socket_send,msg_send.data(),msg_send.size(),0);
    close(socket_send);

    getaddrinfo(NULL,port_receive,&hints_receive,&res_receive);
    socket_receive = socket(res_receive->ai_family,res_receive->ai_socktype,res_receive->ai_protocol);
    bind(socket_receive, res_receive->ai_addr, res_receive->ai_addrlen);
    listen(socket_receive,5);
    socklen_t client_lenght = sizeof(client_address);

    newsocket_receive = accept(socket_receive,(struct sockaddr*)&client_address,&client_lenght);
    cout << "I'm here" << endl;
    int n = recv(newsocket_receive,buffer,sizeof(buffer),0);
    msg_receive.append(buffer, buffer+n);
    cout << msg_receive << endl;
    copy(buffer+n, buffer+256, buffer);
    char subarray[n];
    memset(subarray, '|', n);
    copy(subarray, subarray+n, buffer+256-n);
    close(socket_receive);

}

int main (int argc, char** argv) {

    int n_threads = atoi(argv[1]);
    pthread_t threads[n_threads];

    for (long i=1; i<=n_threads; i++){
        int *arg = (int *) malloc(sizeof(*arg));
        *arg = i;
        pthread_create(&threads[i], NULL, request, arg);
    }

    pthread_exit(NULL);
    return 0;
}

1 个答案:

答案 0 :(得分:0)

您花费大量时间在服务器和客户端之间建立多个连接。我会尝试重新使用客户端与connect()建立的第一个套接字连接,因为套接字是双向的。

就连接机制而言,我看到的第一个问题是你在循环中调用listen()。你应该只为服务器调用一次。