0

I'm working on a C++ project that use sockets to transfer the message, I've done the sending part which looks like this(IDK if it's correct, if no please let me know what should I do)

void CFinalProjectKeithDlg::OnBnClickedSend()
{

    CString ChatMessage;
    SetDlgItemText(IDC_EDIT_CHAT, ChatMessage);
    //const char* pkt = "Message to be sent";
    const char* srcIP = "127.0.0.1";
    const char* destIP = "127.0.0.1";
    sockaddr_in dest;
    sockaddr_in local;
    WSAData data;
    WSAStartup(MAKEWORD(2, 2), &data);

    local.sin_family = AF_INET;
    inet_pton(AF_INET, srcIP, &local.sin_addr.s_addr);
    local.sin_port = htons(0);

    dest.sin_family = AF_INET;
    inet_pton(AF_INET, destIP, &dest.sin_addr.s_addr);
    dest.sin_port = htons(3514);

    SOCKET s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
    bind(s, (sockaddr*)&local, sizeof(local));

    sendto(s, ChatMessage, strlen(ChatMessage), 0, (sockaddr*)&dest, sizeof(dest));

    closesocket(s);
    WSACleanup();

}

Now I'll need to code a receiving part that receives the message. IDK where to start, this is my first real programming project. I really don't know how to start.

Chris
  • 26,361
  • 5
  • 21
  • 42
Keith
  • 1
  • 1

1 Answers1

0

First off, you should not be calling WSAStartup() and WSACleanup() on every send. Call them one time at program startup/exit instead.

Second, you are not doing any error handling whatsoever. Any one of those system calls could fail.

Also, you are sending a blank CString. You meant to use GetDlgItemText() instead of SetDlgItemText().

Now, that being said, to answer your question, the receive code will look similar to this sending code, except that it will need to:

  • create the receiving socket before the message is sent, otherwise the message will get discarded by the OS.
  • bind() the receiving socket to port 3514 instead of 0
  • use recvfrom() instead of sendto()

For example:

// client

CFinalProjectKeithDlg::CFinalProjectKeithDlg()
{
    WSAData data;
    if (WSAStartup(MAKEWORD(2, 2), &data) != 0)
        throw ...;
}

CFinalProjectKeithDlg::~CFinalProjectKeithDlg()
{
    WSACleanup();
}

void CFinalProjectKeithDlg::OnBnClickedSend()
{
    CString ChatMessage;
    GetDlgItemText(IDC_EDIT_CHAT, ChatMessage);

    const char* srcIP = "127.0.0.1";
    const char* destIP = "127.0.0.1";

    sockaddr_in local;
    local.sin_family = AF_INET;
    inet_pton(AF_INET, srcIP, &local.sin_addr);
    local.sin_port = htons(0);

    sockaddr_in dest;
    dest.sin_family = AF_INET;
    inet_pton(AF_INET, destIP, &dest.sin_addr);
    dest.sin_port = htons(3514);

    SOCKET s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
    if (s == INVALID_SOCKET)
        throw ...;

    if (bind(s, (sockaddr*)&local, sizeof(local)) == SOCKET_ERROR) {
        closesocket(s);
        throw ...;
    }

    char *msg = ChatMessage;
    if (sendto(s, msg, strlen(msg), 0, (sockaddr*)&dest, sizeof(dest)) == SOCKET_ERROR) {
        closesocket(s);
        throw ...;
    }

    closesocket(s);
}
// server

private:
    SOCKET s;

CFinalProjectKeithDlg::CFinalProjectKeithDlg()
{
    WSAData data;
    if (WSAStartup(MAKEWORD(2, 2), &data) != 0)
        throw ...;

    const char* srcIP = "127.0.0.1";

    sockaddr_in local;
    local.sin_family = AF_INET;
    inet_pton(AF_INET, srcIP, &local.sin_addr);
    local.sin_port = htons(3514);

    s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
    if (s == INVALID_SOCKET) {
        WSACleanup();
        throw ...;
    }

    if (bind(s, (sockaddr*)&local, sizeof(local)) == SOCKET_ERROR) {
        closesocket(s);
        WSACleanup();
        throw ...;
    }
}

CFinalProjectKeithDlg::~CFinalProjectKeithDlg()
{
    closesocket(s);
    WSACleanup();
}

void CFinalProjectKeithDlg::OnBnClickedRead()
{
    sockaddr_in from;
    int fromlen = sizeof(from);

    char msg[65536] = {};
    if (recvfrom(s, msg, sizeof(msg)-1, 0, (sockaddr*)&from, &fromlen) == SOCKET_ERROR)
        throw ...;

    SetDlgItemText(IDC_EDIT_CHAT, msg);
}
Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
  • I appreciate your answer so much, but I cannot understand why you separate them into different functions like CFinalProjectKeithDlg::CFinalProjectKeithDlg(). My function is linking to the GUI that sending part is the send button in the GUI. And receiving part is a chat box that prints out what it received. ```throw ...;``` Should I implement the "..." to print out the error message? In the server part, I've no idea where to put private: Socket s; I'm sorry for these stupid questions, I just get familiar with sockets. – Keith Apr 15 '22 at 02:41
  • @Keith I already explained why I separated the code. I put the receiving code in a GUI button for demonstration, but in production you are more likely to use a timer or thread to call `recvfrom()` in a loop instead. Yes, you will have to implement the "..." in the `throw`s. Have you ever worked with exceptions? Why are you working with a `class` if you don't understand how it is structured and what `private` means? This has nothing to do with sockets specifically, but to OOP class design in general. Go get yourself some [decent C++ books](https://stackoverflow.com/questions/388242/). – Remy Lebeau Apr 15 '22 at 09:25