如何通过套接字在客户端接收消息?



我正在研究一个使用套接字传输消息的c++项目,我已经完成了发送部分,看起来像这样(IDK如果它是正确的,如果没有,请让我知道我应该怎么做)

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();
}

现在我需要编码一个接收消息的接收部分。IDK从哪里开始,这是我的第一个真正的编程项目。我真不知道该怎么开口。

首先,您不应该在每次发送时都呼叫WSAStartup()WSACleanup()。在程序启动/退出时调用它们一次。

第二,你没有做任何错误处理。这些系统调用中的任何一个都可能失败。

同样,您正在发送一个空白的CString。您的意思是使用GetDlgItemText()而不是SetDlgItemText()

现在,话虽这么说,为了回答你的问题,接收代码将看起来与发送代码相似,除了它需要:

  • 在消息发送之前创建接收套接字,否则消息将被OS丢弃。
  • bind()将接收套接字改为端口3514而不是0
  • 使用recvfrom()代替sendto()
  • 例如:

// 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);
}

最新更新