套接字编程(客户端 - 服务器UDP)

时间:2017-02-09 16:54:07

标签: c sockets udp serversocket

我想构建一个客户端 - 服务器模型,对于连接到服务器的任意数量的客户端,服务器应该发送广播消息。下面是我实现的代码,它没有抛出任何错误,但我看不到服务器和客户端之间发生的任何通信。请告诉我,代码中的问题在哪里。

我希望在客户端系统上看到从服务器传递的消息。

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

2 个答案:

答案 0 :(得分: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;

如果您将通信从客户端转发到服务器,则可以简化代码,从而消除客户端上固定端口号的需要。

答案 1 :(得分:-1)

只需对其进行一些更改。将套接字长度预定义的(socklen_t *)结构分配给类型转换长度

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

socklen_t *将长度转换为套接字长度。 在客户端和服务器端都进行这些更改