簡體   English   中英

套接字編程(客戶端-服務器UDP)

[英]Socket Programming (Client - Server UDP)

我想建立一個客戶端-服務器模型,對於連接到服務器的任何數量的客戶端,服務器都應發送廣播消息。 下面是我實現的代碼,它不會引發任何錯誤,但是我看不到服務器與客戶端之間發生任何通信。 請讓我知道代碼中的問題在哪里。

我希望看到從客戶端系統上的服務器傳遞的消息。

    /************* UDP SERVER CODE *******************/

#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <string.h>
#include <stdlib.h>

int main(int argc, char *argv[]){
  int udpSocket, nBytes, buflen;
  char buffer[1024];
  char string[1024];
  int portNum;
  struct sockaddr_in serverAddr, clientAddr;
  struct sockaddr_storage serverStorage;
  socklen_t addr_size, client_addr_size;
  int i;

  /*Create UDP socket*/
  udpSocket = socket(AF_INET, SOCK_DGRAM, 0);
  portNum=atoi(argv[1]);
  /*Configure settings in address struct*/
  serverAddr.sin_family = AF_INET;
  serverAddr.sin_port = htons(5000);
  serverAddr.sin_addr.s_addr = inet_addr("192.168.1.117");

  memset(serverAddr.sin_zero, '\0', sizeof serverAddr.sin_zero);  

  /*Bind socket with address struct*/
  int bStatus=bind(udpSocket, (struct sockaddr *) &serverAddr, sizeof(serverAddr));
   if (bStatus < 0) {
        printf("error binding on server's port number\n"); 
        exit(1);
  }     


  /*Initialize size variable to be used later on*/
  addr_size = sizeof serverStorage;

memset(&clientAddr, 0, sizeof(clientAddr));
  clientAddr.sin_family = AF_INET;
  clientAddr.sin_port = htons(portNum);  // this is where client is bound
  clientAddr.sin_addr.s_addr = inet_addr("192.168.1.114");

  while(1){
sprintf(buffer,"Hello Client");
  buflen=strlen(buffer);
  int bytesSent = sendto(udpSocket,buffer,buflen,0,(struct sockaddr *)&clientAddr, sizeof(clientAddr));
  if (bytesSent < 0) {
        printf("Error sending/ communicating with client\n");
        exit(1);
  }
  printf("%s\n",buffer);

/*
// ****************************************************

memset(buffer, 0, 1024);
buflen=65536;
recvfrom(udpSocket,buffer,buflen,0,(struct sockaddr *)&serverStorage, &addr_size);
printf("Received from server: %s\n",buffer);  

*/
}

  return 0;
}

下面是客戶端代碼:

     /************* UDP CLIENT CODE *******************/

#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <string.h>

int main(int argc, char *argv[]){
  int clientSocket, portNum, nBytes, buflen;
  char buffer[1024];
  char string[1024];
  struct sockaddr_in serverAddr,clientAddr;
  socklen_t addr_size;

  /*Create UDP socket*/
  clientSocket = socket(AF_INET, SOCK_DGRAM, 0);
 portNum = atoi(argv[1]);
  /*Configure settings in address struct*/
  serverAddr.sin_family = AF_INET;
  serverAddr.sin_port = htons(portNum);
  serverAddr.sin_addr.s_addr = inet_addr("192.168.1.117");

//  memset(serverAddr.sin_zero, '\0', sizeof serverAddr.sin_zero);  
memset(&serverAddr,0,sizeof(serverAddr));


// binding 
bind(clientSocket, (struct sockaddr *) &clientAddr, sizeof(clientAddr));


  /*Initialize size variable to be used later on*/
  addr_size = sizeof serverAddr;

  while(1){

memset(buffer, 0, 1024);
buflen=65536;
recvfrom(clientSocket,buffer,buflen,0,(struct sockaddr *)&serverAddr, &addr_size);
//recvfrom(clientSocket,buffer,buflen,0,NULL,NULL);
printf("Received from server: %s\n",buffer);

/*
//********************************************************************

sprintf(buffer,"Hello Client");    
 buflen=strlen(buffer);
 sendto(clientSocket,buffer,buflen,0,(struct sockaddr *)&serverAddr,addr_size);
 printf("%s\n",buffer);
*/
}

return 0;
}

在較高的層次上,需要解決一些問題。 給定帖子中的代碼有一個服務器,該服務器啟動與客戶端的通信,需要修改以下行(以及與此相關的代碼)

在服務器端:

  sendto(udpSocket,buffer,buflen,0,(struct sockaddr *)&serverStorage,addr_size);

本質上,這里發生的是udpSocket綁定到serverAddr,我們正在嘗試發送到serverStorage(最后一個參數)。 這里的問題是serverStorage沒有綁定任何東西。 基本上sendto具有源權限,但沒有目的地。

在客戶端:

recvfrom(clientSocket,buffer,buflen,0,(struct sockaddr *)&serverAddr, &addr_size);

clientSocket沒有綁定任何東西,因此系統會選擇一個隨機端口進行監聽。 在recvfrom調用中,倒數第二個參數捕獲另一側的地址詳細信息。 盡管在代碼中您已將其綁定到服務器的IP和端口,但是它沒有任何效果,因為它由recvfrom調用填充並返回。

我建議您在這里進行操作(您可以添加詳細信息,但已根據您發布的內容確定了框架)

server_initiating_with_client.c

    //...
    int udpSocket, nBytes, buflen;
    char buffer[1024];
    int portNum;
    struct sockaddr_in serverAddr, clientAddr;
    struct sockaddr_storage serverStorage;
    socklen_t addr_size, client_addr_size;

    /*Create UDP socket*/
    udpSocket = socket(AF_INET, SOCK_DGRAM, 0);
    portNum=atoi(argv[1]);
    /*Configure settings in address struct*/
    memset(&serverAddr, 0, sizeof(serverAddr));
    serverAddr.sin_family = AF_INET;
    serverAddr.sin_port = htons(5000);   // Making sure server has a unique port number
    serverAddr.sin_addr.s_addr = htonl(INADDR_ANY);

    /*Bind socket with address struct*/
    int bStatus = bind(udpSocket, (struct sockaddr *) &serverAddr, sizeof(serverAddr));
    if (bStatus < 0) {
        printf("error binding on server's port number\n");
        exit(1);
    }

    /*Initialize size variable to be used later on*/
    addr_size = sizeof serverStorage;

    /* Because server is initiating the communication here one needs to set the
     * clientAddr and needs to know the port number of the client
     */
    memset(&clientAddr, 0, sizeof(clientAddr));
    clientAddr.sin_family = AF_INET;
    clientAddr.sin_port = htons(portNum);
    clientAddr.sin_addr.s_addr = htonl(INADDR_ANY);

    while(1){
        sprintf(buffer,"Hello Client");   
        buflen=strlen(buffer);
        int bytesSent = sendto(udpSocket,buffer,buflen, 0,
            (struct sockaddr *)&clientAddr, 
            sizeof(clientAddr));
        if (bytesSent < 0) {
            printf("Error sending/ communicating with client\n");
            exit(1);
        }
            printf("Done sending %s\n", buffer);
                sleep(1);
    }
    ..

在客戶端,遵循這些思路

    //..
    int clientSocket, portNum, nBytes, buflen;
    char buffer[1024];
    struct sockaddr_in serverAddr;
    struct sockaddr_in clientAddr;
    socklen_t addr_size;

    /*Create UDP socket*/
    clientSocket = socket(PF_INET, SOCK_DGRAM, 0);
    portNum = atoi(argv[1]);
    /*Configure settings in address struct*/
    memset(&clientAddr, 0, sizeof(clientAddr));
    clientAddr.sin_family = AF_INET;
    clientAddr.sin_port = htons(portNum);
    clientAddr.sin_addr.s_addr = htonl(INADDR_ANY);

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


    /*Bind on client side as well because you are specifically sending something over
    * to the client. Usually the server will know where to talk back to the client
    * but in your example because of the reversed semantics this will be needed
    */

    bind(clientSocket, (struct sockaddr *) &clientAddr, sizeof(clientAddr));

    /*Initialize size variable to be used later on*/
    addr_size = sizeof serverAddr;

    while(1){
        memset(buffer, 0, 1024);
        buflen=65536;
        recvfrom(clientSocket,buffer,buflen,0,(struct sockaddr *)&serverAddr, &addr_size);
        printf("Received from server: %s\n",buffer);
        sleep(1);
    }
    return 0;

如果您將客戶端之間的通訊反向,則可以簡化代碼,從而消除了客戶端上固定端口號的需要。

只需對其進行一些更改。 將套接字長度預定義的(socklen_t *)結構分配給類型轉換長度

n = recvfrom(sockfd, (char *)buffer, MAXLINE,MSG_WAITALL, (struct sockaddr *) &servaddr,  (socklen_t*)&len); 

socklen_t *將長度轉換為套接字長度。 在客戶端和服務器端都進行這些更改。


暫無
暫無

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

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