user2981393
user2981393

Reputation: 519

Receiving multiple client packets on one server

I have 3 applications, one server, 2 clients. I am trying to program this so that I can send a log in request from my clients to the server and request to view information about another client.

Questions: i am using the same ip and port # for all 3 of the applications (it's all done on 3 visual studio applications all on my computer) otherwise I don't think it connects to the server. is this ok?

When I try and use the listen and accept outside of the while loop in the server, it works for one client but not the other. When I try and put the listen and accept inside the while loop it works for both clients but does not respond to more than one accept. What is my issue?

Server

struct Users {

int message;
char userName[50];
char ipAddress[50];
int PortNumber;
bool online;

};

int main () {

//Create users
Users client[2];

client[0].PortNumber = 20000;
client[0].online = false;
sprintf(&client[0].userName[0], "Albert");
sprintf(&client[0].ipAddress[0], "127.0.0.1");

client[1].PortNumber = 20000;
client[1].online = false;
sprintf(&client[1].userName[0], "Monique");
sprintf(&client[1].ipAddress[0], "127.0.0.1");


//Set up all the connection stuff
struct sockaddr_in SvrAddr;
SOCKET WelcomeSocket, ConnectionSocket;
int PortNumber = 20000;
int result;
char IPAddress[] = "127.0.0.1";
char RxBuffer[128];
char TxBuffer[128];


WORD wVersionRequested; 
WSADATA wsaData; 

wVersionRequested = MAKEWORD(2,2); //For Server 


if(WSAStartup(wVersionRequested, &wsaData) != 0) 
    return -1;


//Setting up the welcome socket
WelcomeSocket = socket(AF_INET, SOCK_STREAM, 0);

//Setting up the sockaddr svraddr structure
SvrAddr.sin_family = AF_INET;
SvrAddr.sin_addr.s_addr = inet_addr(IPAddress);
SvrAddr.sin_port = htons(PortNumber);


//Bind
bind(WelcomeSocket, (sockaddr*)&SvrAddr, sizeof(SvrAddr));

//listening
//listen(WelcomeSocket, 5);

//temp users
Users temp;
//ConnectionSocket = accept(WelcomeSocket, NULL, NULL);
ConnectionSocket = SOCKET_ERROR;

//while loop for the connection 
while (1) {

    listen(WelcomeSocket, 5);

    if ((ConnectionSocket = accept(WelcomeSocket, NULL, NULL)) == SOCKET_ERROR)
    {
        return -1;
    }

    else {

    int n = recv(ConnectionSocket, RxBuffer, sizeof(RxBuffer), 0);

    if (n == 0)
        break;


    memcpy(&temp, RxBuffer, sizeof(struct Users));

    //cout << temp.message << temp.userName << endl << endl;

    //check which message type is being sent
    switch(temp.message) {

    //if message type 1
    case 1 :
        for (int i = 0; i < 2; i++) {

            //if receieved username matches with any username in the database
            if (strcmp(temp.userName, client[i].userName) == 0) {

                //assign the recieved users information to the matched one in database
                strcpy(client[i].userName, temp.userName);
                client[i].online = true;
                client[i].message = 2;

                cout << "Username: " << client[i].userName << endl << "Online status: " << client[i].online << endl << endl;

                //send the acknowledgement packet
                send(ConnectionSocket, (char *)&client[i], sizeof(struct Users), 0);
                //closesocket(ConnectionSocket);
            }

        }
        break;

    //if message type 3
    case 3 :

        cout << "User being searched for: " << temp.userName << endl << endl;
        for (int i = 0; i < 2; i++) {

            //if receieved username matches with any username in the database
            if (strcmp(temp.userName, client[i].userName) == 0) {
                client[i].message = 4;
                //send the acknowledgement packet
                send(ConnectionSocket, (char *)&client[i], sizeof(struct Users), 0);
                //closesocket(ConnectionSocket);
            }

        }
        break;

    default :
        break;

    }

}

}

closesocket(ConnectionSocket);
WSACleanup();
}

Client (same for both)

struct Users {

int message;
char userName[50];
char ipAddress[50];
int PortNumber;
bool online;

};


int main () {

struct sockaddr_in SvrAddr;
SOCKET ClientSocket;
int PortNumber = 20000;
char IPAddress[] = "127.0.0.1";
//char message[] = "Hello this is the client.";
char RxBuffer[128];

WORD wVersionRequested; 
WSADATA wsaData; 

wVersionRequested = MAKEWORD(2,3); //For Client 

if(WSAStartup(wVersionRequested, &wsaData) != 0) 
    return -1; 


ClientSocket = socket(AF_INET, SOCK_STREAM, 0);

SvrAddr.sin_family = AF_INET;
SvrAddr.sin_addr.s_addr = inet_addr(IPAddress);
SvrAddr.sin_port = htons(PortNumber);

connect(ClientSocket, (sockaddr*)&SvrAddr, sizeof(SvrAddr));



//cout << "Name: ";
//cin >> login;

//Send request to login
int log;
char * name = new char[128];
char * request = new char[128];
Users client;
Users talkto;


do {

    cout << "To login press (1) to end press (2). ";
    cin >> log;
    flushall();

    if (log == 1) {

        cout << "Username : ";
        cin.getline(name, 128, '\n');
        cout << endl;
        flushall();

        //Set client login info
        strcpy(client.userName, name);
        client.message = 1;



        send(ClientSocket, (char *)&client, sizeof(struct Users), 0);


        //Recieve acknowledgement
        recv(ClientSocket, RxBuffer, sizeof(RxBuffer), 0);
        //create temp users
        Users temp;

        memcpy(&temp, RxBuffer, sizeof(struct Users));

        //If logged in and received a message of type 2 (acknowledgement)
        if (temp.message == 2) {

            cout << "You have logged in." << endl << endl;

            cout << "Enter user to request user information: ";
            cin.getline(talkto.userName, 128, '\n');
            flushall();
            cout << endl;

            talkto.message = 3;

            //send request for user information packet
            send(ClientSocket, (char *)&talkto, sizeof(struct Users), 0);

            recv(ClientSocket, RxBuffer, sizeof(RxBuffer), 0);

            memcpy(&temp, RxBuffer, sizeof(struct Users));

            //if message received is of type 4 (acknowledgement of user request info)
            if (temp.message == 4) {

                cout << "Requested User: " << temp.userName << endl << "Online status: " << temp.online << endl << endl;
            }
        }

        //cout << temp.userName << endl << temp.online << endl << temp.message;
    } 

} while (log != 2);


closesocket(ClientSocket);


WSACleanup();



} 

Upvotes: 1

Views: 147

Answers (1)

You dont use the listen() inside the loop. Only the accept(). Also you dont use a nonblocking socket, but that is your preference. Another thing, every time you finish the accept you must use closesocket. Also your recv() must be handled in a loop because unlike send it may return before it receives all of the data.

Your basic structure for the server:

struct sockaddr_in inAddr; //incoming address. Use it to distinguise between incoming clients
struct sockaddr_in address;
unsigned int inLen;
int recvMsgSize;
unsigned short port = 20000;
Socket socket_handle, acceptSocket;

socket_handle = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if(socket_handle == INVALID_SOCKET){
    //error
}

memset(&address, 0, sizeof(address));
address.sin_family = AF_INET;
address.sin_addr.s_addr = htonl(INADDR_ANY); //All incoming addresses
address.sin_port = htons(port); //port must be unsigned short not int!
if(bind(socket_handle, (struct sockaddr *)&address, sizeof(address)) < 0){
    //error
}

if(listen(socket_handle, MAXPENDING) < 0){
    //error
}

while(true){
    acceptSocket = accept(socket_handle, (struct sockaddr *) &inAddr, &inLen));
    if(acceptSocket == INVALID_SOCKET){
        //error
    }

    while(true){
        recvMsgSize = recv(acceptSocket, received_data, strlen(received_data), 0);
        if(recvMsgSize < 0){/*error*/}
        else if(recvMsgSize == 0){break;}
        else{/*receive your data*/}
    }

    (do other stuff...)
    closesocket(acceptSocket);
}

closesocket(socket_handle);
WSACleanup();

valter

Upvotes: 1

Related Questions