Update data's clients in 1 server-n clients socket c++ mfc application

306 Views Asked by At

I making a simple check login program with mfc. Im using WSAAsyncselect function to make a non blocking socket. Everytimes theres someone login, the server will send back to all current client a message "user x has login in" and then, they will show that message on their message log.

Usually, i can only update value from a button calling WSAAsyncselect funtion after send the data to server. for example

void CClientDlg::OnBnClickedLogin()
{
    // TODO: Add your control notification handler code here
    UpdateData(TRUE);
    if ((m_username == "") || (m_password == ""))
    {
        return;
    }
    client = socket(AF_INET, SOCK_STREAM, 0);
    if (client == INVALID_SOCKET)
    {
        return;
    }
    serverAddr.sin_family = AF_INET;
    serverAddr.sin_port = htons(PORT);
    char* IPstr = CT2A(IP);
    serverAddr.sin_addr.s_addr = inet_addr(IPstr);
    int error = connect(client, (sockaddr*)&serverAddr, sizeof(serverAddr));
    if (error == SOCKET_ERROR) {
        return;
    }

    modestr = _T("1 ") + m_username + _T(",") + m_password;
    SendInfo(modestr);
    WSAAsyncSelect(client, m_hWnd, WM_SOCKET, FD_READ | FD_CLOSE);
    UpdateData(FALSE);
}

On server, i have this

BEGIN_MESSAGE_MAP(CServerDlg, CDialogEx)
    ON_WM_SYSCOMMAND()
    ON_WM_PAINT()
    ON_WM_QUERYDRAGICON()
    ON_MESSAGE(WM_SOCKET, SockMsg)
END_MESSAGE_MAP()
LRESULT CServerDlg::SockMsg(WPARAM wParam, LPARAM lParam) {
    if (WSAGETSELECTERROR(lParam))
    {
        closesocket(wParam);
        MessageBox(_T("error"));
    }
    switch (WSAGETSELECTEVENT(lParam))
    {
    case FD_ACCEPT:
    {
        //accept client
        clientSocks.push_back(CLIENT(accept(wParam, NULL, NULL), "unidentified user"));

        break;
    }
    case FD_READ:
    {
        //check login codes
        //check login codes 
        //check login codes
                for (int i = 0; i < num_clients; i++) {
                    CString message = _T("0 ") + CString(user.c_str()) + _T("login\r\n");
                    SendResponse(clientSocks[i].clientSocket, message); //a send funtion to send data to 
                    //another socker
                }
}

There's anyway to update data automatically after the server send data to these clients

1

There are 1 best solutions below

0
j6t On

Not answering your question, because this text would be too long for a comment.

I think you are completely misunderstanding how WSAAsyncSelect works. The function does not open a second communication channel from the "client" to the "server" that is based on Windows messages. (There is already a channel: the network connection via sockets.)

You use WSAAsyncSelect to allow that the data transfer happens in the background while the user interface's message loop can keep running and can respond to user activity.

The nMsg argument, WM_SOCKET in your case, is not sent across to a different executable, but is sent to the application itself when the requested event happens. These tell "hey, I've just received data!", "hey, the network connection was closed", "hey, there's now room to write more data".

In your example, it does not make sense to request FD_READ events when the application does not read data.

In addition, since both your "client" and your "server" seem to be user interface applications, both should use WSAASyncSelect. The sending side would listen for FD_WRITE | FD_CLOSE events (because it has to write data), and the receiving side would listen to FD_READ | FD_CLOSE events (because it has to read data).

Note that, in general, the sending side that uses WSAAsyncSelect becomes very complicated to implement: It is not just a simple single write(), because it must be prepared that not all data can be sent at once. Rather, it must keep the data to be sent around, must keep a record of how much has been sent and what has not been sent, yet. Therefore, when the packets are small (a few hundred bytes at most) and infrequent, I would not use asynchronous communication in the sender, and would just hope that networking layer in the OS would be able to cache the data for me and would not block the write() call.