The same Winsock client server sends and receives at the same time

I have a problem with a simple Winsock C ++ chat application. I wrote code that allows the user to choose whether he wants to send data or receive data, and depending on the user's choice, the corresponding functions are executed. What I would like to achieve is that the user can BOTH send and receive data. How can I approach him? Please note that I do not want to use multiple clients, I just want to send and receive data over the server, and also send and receive data by the client at the same time.

Edit: I've added my code.

#include <WinSock2.h>
#include <Windows.h>
#include <iostream>
#include <string>
#include <stdio.h>
#include <ctime>


int main()
{
    string IP;
    int userType;

    // Ask the user if he is server or client
    cout << "Hi, which type of user are you? 1 - Server, 2 - Client" <<endl;
    cin >> userType;

    // depending on the declared user type, execute the appropriate code
    if (userType == 1)
    {
        //initialize winsock and create a socket
        WSAData wsaData; // initialize
        iResult = WSAStartup(MAKEWORD(2,1), &wsaData);

        if (iResult != NO_ERROR) // check for errors
             cout << "Error at WSAStartup()" <<endl;
        else
             cout << "WSAStartup() is OK." <<endl;

        // create socket
        sockSocket = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP); // create a socket
        if (sockSocket == INVALID_SOCKET) // check for errors
        {
            cout << "Error at socket(): " << WSAGetLastError();
            WSACleanup();
            return true;
        }
        else
            cout << "Socket() is OK." <<endl;
        return true;

        // bind to socket
        service.sin_addr.s_addr = inet_addr("0.0.0.0");
        service.sin_family = AF_INET;
        service.sin_port = htons(55555);

        if (bind(sockSocket, (SOCKADDR*)&service, sizeof(service)) == SOCKET_ERROR) // cheking for errors
        {
            cout << "Bind() failed." << endl;
            closesocket(sockSocket);
            return true;
        }
        else
            cout << "Bind() is OK." <<endl;


        // listen
        listen(sockSocket, SOMAXCONN);
        if (listen(sockSocket, 10) == SOCKET_ERROR) // check for errors
        {
            cout << "Error listening on socket." << endl;
            return true;
        }
        else
            cout << "Listen() is OK." <<endl;

        //accept connection
        servlen = sizeof(service);
        cout << "Waiting for user to connect..." << endl;

        acceptSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
        if(acceptSocket = accept(sockSocket, (SOCKADDR*)&service, &servlen))
        {
            cout << "A coonnection was found" <<endl<<endl;
        }
        sockSocket = acceptSocket;

        // receive messages
        do
        {
            std::string message;
            char Buffer[512];
            iResult = recv(sockSocket, Buffer, 512, 0);
            Buffer[iResult] = '\0';
            message = Buffer;
            currentDate();
            std::cout << Buffer <<endl<<endl;

        }while(iResult>0);

        closesocket(sockSocket);
        WSACleanup();
    }

    else if (userType == 2)
    {
        // exactly the same code as for server part to initialize and create socket

        // ask  for the ip the user wants to connect to
        cout << "Hi what the IP that you want to connect to?" <<endl;
        cin >> IP;

        // connect to socket
        conService.sin_addr.s_addr = inet_addr(IP); // connect to the ipnuted IP
        conService.sin_family = AF_INET;
        conService.sin_port = htons(55555); // should the port also be the argument?

        if (connect(sockSocket, (SOCKADDR*)&conService, sizeof(conService)) == SOCKET_ERROR) // check for errors
        {
            cout << "Failed to connect: " << WSAGetLastError();
            WSACleanup();
            return true;
        }
        else
        {
            cout << "Connected." <<endl;
        }

        // send messages
        for (;;)
        {
            std::string message;
            std::getline(std::cin, message);
            unsigned int Length = strlen(message.c_str());
            if(Length>512)
                Length = 512;
            currentDate();
            iResult = send(sockSocket, message.c_str(),Length,0);
        }
        closesocket(sockSocket);
        WSACleanup();
    }

    WSACleanup();
    return 0;
}

      

Edit2: As LeMay said in a comment, I need to have a second thread (since the first one is just what's going on in the main function). From what I understood, I can use the CreateThread function. My problem for both sending and receiving messages is solved (I have to create another thread) but now I have a problem implementing the solution. As I wrote in the comment below LeMay's answer, I get an error like this, referencing the line where I use the CreateThread function (HANDLE hThread = CreateThread (0,0, & ReadThread, acceptSocket, 0, & dwThreadID);):

  • invalid conversion from 'SOCKET {aka unsigned int}' to 'PVOID {aka void *}' [-fpermissive] | and
  • invalid conversion from 'DWORD {aka long unsigned int}' to 'PDWORD {aka long unsigned int *}' [-fpermissive]

Any hints on this? Hopefully this makes my question more specific (if not, tell me that I should specify more).

+3


source to share


1 answer


You want the client and server to read continuously in the background for the lifetime of the connection, and then they can send data in parallel when needed. Move your reading logic to a separate thread, for example:



#include <WinSock2.h>
#include <Windows.h>
#include <iostream>
#include <string>
#include <stdio.h>
#include <ctime>

DWORD WINAPI ReadingThread(LPVOID param)
{
    SOCKET s = (SOCKET) param;
    char Buffer[512];
    int iResult;

    do
    {
        iResult = recv(s, Buffer, 512, 0);
        if (iResult <= 0) break;
        Buffer[iResult] = '\0';
        std::cout << "Recv: " << message << std::endl;
    }
    while (true);

    return 0;
}

int main()
{
    int userType;
    HANDLE hThread;
    DWORD dwThreadID;

    //initialize winsock and create a socket
    WSAData wsaData; // initialize
    iResult = WSAStartup(MAKEWORD(2,1), &wsaData);

    if (iResult != NO_ERROR) // check for errors
    {
        std::cout << "Error at WSAStartup()" << std::endl;
        return 0;
    }

    std::cout << "WSAStartup() is OK." << std::endl;

    // Ask the user if he is server or client
    std::cout << "Hi, which type of user are you? 1 - Server, 2 - Client" << std::endl;
    std::cin >> userType;

    // depending on the declared user type, execute the appropriate code
    if (userType == 1)
    {
        // create socket
        sockSocket = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP); // create a socket
        if (sockSocket == INVALID_SOCKET) // check for errors
        {
            std::cout << "Error at socket(): " << WSAGetLastError() << std::endl;
            WSACleanup();
            return 0;
        }

        std::cout << "Socket() is OK." << std::endl;

        // bind to socket
        service.sin_addr.s_addr = INADDR_ANY;
        service.sin_family = AF_INET;
        service.sin_port = htons(55555);

        if (bind(sockSocket, (SOCKADDR*)&service, sizeof(service)) == SOCKET_ERROR) // cheking for errors
        {
            std::cout << "Error at bind(): " << WSAGetLastError() << std::endl;
            closesocket(sockSocket);
            WSACleanup();
            return 0;
        }

        std::cout << "Bind() is OK." << std::endl;

        // listen
        if (listen(sockSocket, 10) == SOCKET_ERROR) // check for errors
        {
            std::cout << "Error at listen(): " << WSAGetLastError() << std::endl;
            closesocket(sockSocket);
            WSACleanup();
            return 0;
        }

        std::cout << "Listen() is OK." << std::endl;

        //accept connection
        servlen = sizeof(service);
        std::cout << "Waiting for user to connect..." << std::endl;

        acceptSocket = accept(sockSocket, (SOCKADDR*)&service, &servlen);
        if (acceptSocket != INVALID_SOCKET)
        {
            std::cout << "Error at accept(): " << WSAGetLastError() << std::endl;
            closesocket(sockSocket);
            WSACleanup();
            return 0;
        }

        std::cout << "A client has connected" << std::endl << std::endl;

        // receive messages
        hThread = CreateThread(NULL, 0, &ReadingThread, (void*)acceptSocket, 0, &dwThreadID);
        if (!hThread)
        {
            std::cout << "Error at CreateThread(): " << GetLastError() << std::endl;
            closesocket(acceptSocket);
            closesocket(sockSocket);
            WSACleanup();
            return 0;
        }

        // send messages
        do
        {
            std::string message;
            if (!std::getline(std::cin, message))
                break;

            if (send(acceptSocket, msg.c_str(), msg.length(), 0) == SOCKET_ERROR)
            {
                std::cout << "Error at send(): " << WSAGetLastError() << std::endl;
                break;
            }
        }
        while (true);

        closesocket(acceptSocket);

        WaitForSingleObject(hThread, INFINITE);
        CloseHandle(hThread);

        closesocket(sockSocket);
        WSACleanup();
    }

    else if (userType == 2)
    {
        // create socket
        sockSocket = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP); // create a socket
        if (sockSocket == INVALID_SOCKET) // check for errors
        {
            std::cout << "Error at socket(): " << WSAGetLastError() << std::endl;
            WSACleanup();
            return 0;
        }

        std::cout << "Socket() is OK." << std::endl;

        // ask  for the ip the user wants to connect to
        std::string IP;
        std::cout << "Hi what the IP that you want to connect to?" << std::endl;
        std::cin >> IP;

        // connect to socket
        conService.sin_addr.s_addr = inet_addr(IP.c_str()); // connect to the ipnuted IP
        conService.sin_family = AF_INET;
        conService.sin_port = htons(55555); // should the port also be the argument?

        if (connect(sockSocket, (SOCKADDR*)&conService, sizeof(conService)) == SOCKET_ERROR) // check for errors
        {
            std::cout << "Failed to connect: " << WSAGetLastError() << std::endl;
            closesocket(sockSocket);
            WSACleanup();
            return 0;
        }

        std::cout << "Connected." << std::endl;

        // receive messages
        hThread = CreateThread(NULL, 0, &ReadingThread, (void*)sockSocket, 0, &dwThreadID);
        if (!hThread)
        {
            std::cout << "Error at CreateThread(): " << GetLastError() << std::endl;
            closesocket(sockSocket);
            WSACleanup();
            return 0;
        }

        // send messages
        do
        {
            std::string message;
            if (!std::getline(std::cin, message))
                break;

            if (send(sockSocket, msg.c_str(), msg.length(), 0) == SOCKET_ERROR)
            {
                std::cout << "Error at send(): " << WSAGetLastError() << std::endl;
                break;
            }
        }
        while (true);

        closesocket(sockSocket);

        WaitForSingleObject(hThread, INFINITE);
        CloseHandle(hThread);

        WSACleanup();
    }

    else
    {
        std::cout << "Invalid type entered!" << std::endl;
        WSACleanup();
        return 0;
    }

    return 0;
}

      

+5


source







All Articles