簡體   English   中英

如何使用Eclipse在C ++中測試和運行客戶端服務器程序

[英]How to Test and Run a Client Server Program in C++ using Eclipse

我正在嘗試使用UDP,並想測試和調試一些客戶端服務器程序。

我正在使用帶有cygwin64的Eclipse IDE作為編譯器。

我從這里找到了一些示例客戶端服務器程序: https : //www.geeksforgeeks.org/udp-server-client-implementation-c/

我希望能夠運行該示例,以使我開始學習UDP客戶端服務器。

示例代碼如下:

服務器

    // Server side implementation of UDP client-server model
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>

#define PORT     8080
#define MAXLINE 1024

// Driver code
int main() {
    int sockfd;
    char buffer[MAXLINE];
    char *hello = "Hello from server";
    struct sockaddr_in servaddr, cliaddr;

    // Creating socket file descriptor
    if ( (sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0 ) {
        perror("socket creation failed");
        exit(EXIT_FAILURE);
    }

    memset(&servaddr, 0, sizeof(servaddr));
    memset(&cliaddr, 0, sizeof(cliaddr));

    // Filling server information
    servaddr.sin_family    = AF_INET; // IPv4
    servaddr.sin_addr.s_addr = INADDR_ANY;
    servaddr.sin_port = htons(PORT);

    // Bind the socket with the server address
    if ( bind(sockfd, (const struct sockaddr *)&servaddr,
            sizeof(servaddr)) < 0 )
    {
        perror("bind failed");
        exit(EXIT_FAILURE);
    }



    int len, n;
    n = recvfrom(sockfd, (char *)buffer, MAXLINE,
                MSG_WAITALL, ( struct sockaddr *) &cliaddr,
                &len);
    buffer[n] = '\0';
    printf("Client : %s\n", buffer);
    sendto(sockfd, (const char *)hello, strlen(hello),
        0, (const struct sockaddr *) &cliaddr,
            len);
    printf("Hello message sent.\n");

    return 0;
}

客戶

// Client side implementation of UDP client-server model 
#include <stdio.h> 
#include <stdlib.h> 
#include <unistd.h> 
#include <string.h> 
#include <sys/types.h> 
#include <sys/socket.h> 
#include <arpa/inet.h> 
#include <netinet/in.h> 

#define PORT     8080 
#define MAXLINE 1024 

// Driver code 
int main() { 
    int sockfd; 
    char buffer[MAXLINE]; 
    char *hello = "Hello from client"; 
    struct sockaddr_in     servaddr; 

    // Creating socket file descriptor 
    if ( (sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0 ) { 
        perror("socket creation failed"); 
        exit(EXIT_FAILURE); 
    } 

    memset(&servaddr, 0, sizeof(servaddr)); 

    // Filling server information 
    servaddr.sin_family = AF_INET; 
    servaddr.sin_port = htons(PORT); 
    servaddr.sin_addr.s_addr = INADDR_ANY; 

    int n, len; 

    sendto(sockfd, (const char *)hello, strlen(hello), 
        MSG_CONFIRM, (const struct sockaddr *) &servaddr,  
            sizeof(servaddr)); 
    printf("Hello message sent.\n"); 

    n = recvfrom(sockfd, (char *)buffer, MAXLINE,  
                MSG_WAITALL, (struct sockaddr *) &servaddr, 
                &len); 
    buffer[n] = '\0'; 
    printf("Server : %s\n", buffer); 

    close(sockfd); 
    return 0; 
} 

我嘗試打開兩個不同的Eclipse工作台並運行兩個代碼,但是它沒有按預期運行,並且說消息已發送,但是我無法在客戶端或服務器上接收到它們。

我絕對想堅持使用c / c ++並嘗試在可能的情況下使其在eclipse中工作。

如果有人對我如何能夠看到一些結果或任何可以幫助我開始的事情有任何建議,將不勝感激。 謝謝!

問題

您尚未在客戶端代碼中正確設置服務器的地址。

servaddr.sin_addr.s_addr = INADDR_ANY;

發送時毫無意義(為什么要發送到任何可用地址?要發送到服務器。),並被sendto拒絕。 如果您檢查了返回值,您將已經看到了。 始終檢查返回值,即使對於UDP通信也是如此。 當然,有100萬個原因導致數據包無法通過sendto時無法檢測到的UDP到達,但是很高興知道網絡堆棧實際上已經接受了該消息,即使隨后有一個垃圾吞噬了該數據包也是如此。互聯網的黑暗角落。 您可以做一些發送錯誤,例如perror ,然后相應地修復代碼。 煙,不是很多。 您必須使協議足夠健壯,以重新傳輸或以其他方式在丟失數據包后幸免。

使用getaddrinfo獲取服務器的地址結構。

更換

// Filling server information 
servaddr.sin_family = AF_INET; 
servaddr.sin_port = htons(PORT); 
servaddr.sin_addr.s_addr = INADDR_ANY; 

與更像

struct addrinfo hints;
struct addrinfo *hostlist;
memset(&hints, 0, sizeof(struct addrinfo));
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_DGRAM;
hints.ai_flags = 0;
hints.ai_protocol = IPPROTO_UDP; 

if (getaddrinfo("Server Name or Address Goes Here",
                PORT, // this needs to be a char *, not an integer
                &hints,
                &hostlist))
{
    // handle error
    exit(EXIT_FAILURE);
}

在這種情況下, PORT需要為char * ,因此不是

#define PORT     8080 

采用

constexpr char const * PORT = "8080";

如果編譯器較舊且不支持constexprconstexpr

然后,當你去送,遍歷的hostlist ,直到找到響應的主機。 由於您可能已經將服務器縮小為僅一個候選服務器,因此這可能有些過頭,但是您也可以練習正確地做事。 當系統開始變得復雜時,這種選擇很爛。

struct addrinfo *curhost;
for (curhost = hostlist; curhost != NULL; curhost = curhost->ai_next)
{
    int rval = sendto(sockfd,
                      (const char *) hello,
                      strlen(hello),
                      0,
                      curhost->ai_addr,
                      curhost->ai_addrlen);
    if (rval> 0) // always check return codes. Programmers are lazy. 
                 // They wouldn't have gone to the effort of putting
                 // it there if it wasn't important.
    {
        if server responds
            do protocol stuff to complete transaction
            break;
    }
}
freeaddrinfo(hostlist); // thou shalt not leak resources.
if (curhost == nullptr)
{
    notify user that no server was willing to talk
}

getaddrinfo文檔。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM