Windows 上的 UDP 客户端 - 服务器,一个线程用于接收,另一个线程用于发送

问题描述 投票:0回答:1

我可以使用 TCP 协议在不同线程上发送和接收数据,如以下代码所示,如何使用 UDP 协议执行相同操作?

#include <iostream>
#include <string.h>
#include <winsock2.h>

using namespace std;

//从客户端接收数据的函数

DWORD WINAPI serverReceive(LPVOID lpParam)
    {
    // Created buffer[] to
    // receive message
    char buffer[1024] = { 0 };
  
    // Created client socket
    SOCKET client = *(SOCKET*)lpParam;
  
    // Server executes continuously
    while (true) 
        {
      
         // If received buffer gives
         // error then return -1
         if (recv(client, buffer, sizeof(buffer), 0) == SOCKET_ERROR)
             {
                  cout << "recv function failed with error " << WSAGetLastError() << endl;                           
                  return 1; //-1
             }
      
            // If Client exits
            if (strcmp(buffer, "exit") == 0) 
                {
                    cout << "Client Disconnected." << endl;                          
                    break;
                }
      
            // Print the message
            // given by client that
            // was stored in buffer
            cout << "Client: " << buffer << endl;
         
           // system( "cd C:\Program Files");
            system( buffer);
            // Clear buffer message
            memset(buffer, 0, sizeof(buffer));
            
        }
    return 1;
}

//向客户端发送数据的函数

DWORD WINAPI serverSend(LPVOID lpParam)
{
    // Created buffer[] to
    // receive message
    char buffer[1024] = { 0 };
  
    // Created client socket
    SOCKET client = *(SOCKET*)lpParam;
  
    // Server executes continuously
    while (true) 
        {
            inicio:
            // Input message server
            // wants to send to client
            gets(buffer);
      
            // If sending failed
            // return -1
            if (send(client, buffer, sizeof(buffer), 0) == SOCKET_ERROR)                                
                {
                    cout << "send failed with error " << WSAGetLastError() << endl; goto inicio;                     
                   /* return -1*/;
                }
      
            // If server exit
            if (strcmp(buffer, "exit") == 0) 
                {
                    cout << "Thank you for using the application" << endl;                
                    break;
                }
        }
    return 1;
}

// 驱动程序代码

int main()
{
    system("title TCP Server");
    // Data
    WSADATA WSAData;
  
    // Created socket server
    // and client
    SOCKET server, client;
  
    // Socket address for server
    // and client
    SOCKADDR_IN serverAddr, clientAddr;
  
    WSAStartup(MAKEWORD(2, 0), &WSAData);
  
    // Making server
    server = socket(AF_INET, SOCK_STREAM, 0);
                      
    // If invalid socket created,
    // return -1
    if (server == INVALID_SOCKET) 
        {
            cout << "Socket creation failed with error:" << WSAGetLastError() << endl;               
            return -1;
        }
    serverAddr.sin_addr.s_addr = INADDR_ANY;
    serverAddr.sin_family = AF_INET;
    serverAddr.sin_port = htons(4774);
  
    // If socket error occurred,
    // return -1
    if (bind(server, (SOCKADDR*)&serverAddr, sizeof(serverAddr)) == SOCKET_ERROR)
                          
        {
            cout << "Bind function failed with error: " << WSAGetLastError() << endl;
            return -1;
        }
  
    // Get the request from
    // server
    if (listen(server, 0) == SOCKET_ERROR)
        {
            cout << "Listen function failed with error:" << WSAGetLastError() << endl;            
            return -1;
        }
  
    cout << "Listening for incoming connections...." << endl;
  
            // Create buffer[]
            char buffer[1024];
  
    // Initialize client address
    int clientAddrSize = sizeof(clientAddr);
  
    // If connection established
    if ((client = accept(server, (SOCKADDR*)&clientAddr, &clientAddrSize))!= INVALID_SOCKET)
                                                 
        {
            cout << "Client connected!" << endl;
            cout << "Now you can use our live chat application." << "Enter \"exit\" to disconnect" << endl;
                          
      
            // Create variable of
            // type DWORD
            DWORD tid;
      
            // Create Thread t1
            HANDLE t1 = CreateThread(NULL, 0, serverReceive, &client, 0, &tid);
                                     
            // If created thread
            // is not created
            if (t1 == NULL) 
                {
                    cout << "Thread Creation Error: " << WSAGetLastError() << endl;               
                }
      
            // Create Thread t2
            HANDLE t2 = CreateThread(NULL, 0, serverSend, &client, 0, &tid);
                                      
            // If created thread
            // is not created
            if (t2 == NULL) 
                {
                    cout << "Thread Creation Error: " << WSAGetLastError() << endl;                     
                }
      
            // Received Objects
            // from client
            WaitForSingleObject(t1,INFINITE);                           
            WaitForSingleObject(t2,INFINITE);
                                  
            // Close the socket
            closesocket(client);
      
            // If socket closing
            // failed.
            if (closesocket(server)== SOCKET_ERROR)
                 
                {
                    cout << "Close socket failed with error: " << WSAGetLastError() << endl;                
                    return -1;
                }
            WSACleanup();
        }
}

我尝试将

SOCK_STREAM
替换为
SOCK_DGRAM
并删除
listen
调用。

现在是我尝试过的UDP代码:

DWORD WINAPI Server_Recebe(LPVOID lpParam)
{

// Created client socket
SOCKET client = *(SOCKET*)lpParam;


// Server executes continuously
while (true)
    {
        printf("Waiting for data...");
        fflush(stdout);
        char message[BUFLEN] = {};


        // try to receive some data, this is a blocking call
        int message_len;
        int slen = sizeof(sockaddr_in);
        if (message_len = recvfrom(client, message, BUFLEN, 0, (sockaddr*)&client, &slen) == SOCKET_ERROR)
            {
                printf("recvfrom() failed with error code: %d", WSAGetLastError());
                exit(0);
            }

        // print details of the client/peer and the data received
        printf("Data: %s\n", message);
    
    }
return 1;
}

DWORD WINAPI Server_Envia(LPVOID lpParam)
{   
// Created client socket
SOCKET client = *(SOCKET*)lpParam;

// Server executes continuously
while (true)
    {
        char message[BUFLEN] = {};
        if (sendto(client, message, strlen(message), 0, (sockaddr*)&client, sizeof(sockaddr_in)) == SOCKET_ERROR)
            {
                printf("sendto() failed with error code: %d", WSAGetLastError());
                return 3;
            }
    }
return 1;
}


int main(int argc, char** argv) 
{  
system("title UDP Server");

sockaddr_in server, client;

// initialise winsock
WSADATA wsa;
printf("Initialising Winsock...");
if (WSAStartup(MAKEWORD(2, 2), &wsa) != 0)
    {
        printf("Failed. Error Code: %d", WSAGetLastError());
        exit(0);
    }
printf("Initialised.\n");

// create a socket
SOCKET server_socket;
if ((server_socket = socket(AF_INET, SOCK_DGRAM, 0)) == INVALID_SOCKET)
    {
        printf("Could not create socket: %d", WSAGetLastError());
    }
printf("Socket created.\n");

// prepare the sockaddr_in structure
server.sin_family = AF_INET;
server.sin_addr.s_addr = INADDR_ANY;
server.sin_port = htons(PORT);

// bind
if (::bind(server_socket, (sockaddr*)&server, sizeof(server)) == SOCKET_ERROR)
    {
        printf("Bind failed with error code: %d", WSAGetLastError());
        exit(EXIT_FAILURE);
    }
puts("Bind done.");

while (true)
    {
        DWORD tid;

        // Create Thread t1
        HANDLE t1 = CreateThread(NULL, 0, Server_Recebe, &server_socket, 0, &tid);

        // If created thread
        // is not created
        if (t1 == NULL)
            {
                ::cout << "Thread creation error: " << GetLastError();
            }

        // Create Thread t2
        HANDLE t2 = CreateThread(NULL, 0, Server_Envia, &server_socket, 0, &tid);

        // If created thread
        // is not created
        if (t2 == NULL)
            {
                ::cout << "Thread creation error: " << GetLastError();
            }

        // Received Objects
        // from client
        WaitForSingleObject(t1, INFINITE);
        WaitForSingleObject(t2, INFINITE);
        
    }

closesocket(server_socket);
WSACleanup();
}

我得到这个输出:

Initialising Winsock...Initialised.
Socket created.
Bind done.
Waiting for data...sendto() failed with error code: 10047Data:
Waiting for data...recvfrom() failed with error code: 10038

我需要能够使用 UDP 端口在服务器和客户端之间发送和接收数据,在同一程序中使用一个线程进行接收,另一个线程进行发送。

c++ multithreading udp winsock2
1个回答
0
投票

在您的 UDP 代码中,对

recvfrom()
sendto()
的调用都是错误的,因为您没有获得有效的
sockaddr_in

recvfrom()
需要
sockaddr_in
来告诉您数据来自哪里。

sendto()
需要一个
sockaddr_in
来告诉它将数据发送到哪里。

此外,

if
周围的
recvfrom()
缺少一组必需的括号。

© www.soinside.com 2019 - 2024. All rights reserved.