基本的UDP客户端/服务器不起作用?

时间:2017-12-29 19:50:39

标签: c sockets

我希望这是对我的问题的一个相对简单的答案。我试图学习如何在套接字中编程,我似乎无法使基本的UDP示例正常工作。我试图发送一个字符串"你好"从一台计算机到另一台计算机在屏幕上阅读它。

我从这个网站开始 https://www.programminglogic.com/sockets-programming-in-c-using-udp-datagrams/

然后尝试: https://www.abc.se/~m6695/udp.html

我也看过了 https://www.cs.rutgers.edu/~pxk/417/notes/sockets/udp.html

但似乎每次我尝试编码都没有任何反应。我没有错,我只是没有得到任何沟通。我至少可以从客户端计算机ping我的服务器计算机

我的设置: 我目前有两台计算机,一台运行Ubuntu 16.04,另一台运行14.04。 我希望通过直接连接它们来开始简单的事情。但我试过通过开关连接它们。没有成功。

在"服务器"计算机我通过打开终端来设置我的网卡

sudo ifconfig enps60 192.168.1.1 netmask 255.255.255.0

要在终端I中创建我的服务器代码,请输入

gedit udp_server.c

并在文本编辑器中输入

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

int main()
{
    int udpSocket, nBytes;
    char buffer[1024];
    struct sockaddr_in serverAddr, cientAddr;
    struct sockaddr_storage serverStorage;
    socklen_t addr_size, client_addr_size;


    /* Create UDP socket */
    udpSocket = socket(AF_INET, SOCK_DGRAM, 0);

    /* Configure settings in address struct */
    serverAddr.sin_family = AF_INET;
    serverAddr.sin_port = htons(0);
    serverAddr.sin_addr.s_addr = inet_addr("192.168.1.1");
    memset(serverAddr.sin_zero, '\0', sizeof(serverAddr.sin_zero));

    /* Bind Socket */
    bind(udpSocket, (struct sockaddr *)&serverAddr, sizeof(serverAddr));
    printf("bind complete. Port number = %d\n", ntohs(serverAddr.sin_port));

    addr_size = sizeof(serverStorage);

    while(1)
    {
        nBytes = recvfrom(udpSocket, buffer, 1024, 0, (struct sockaddr *)%clientAddr, &addr_size);
        printf("any bytes: %d\n, nBytes);
    }

}

然后我通过输入在终端中编译我的代码 gcc -o udp_server udp_server.c

在我的客户端计算机上(ubuntu 14.04)我打开终端并输入

sudo ifconfig eth0 192.168.1.2 netmask 255.255.255.0

然后在终端I中创建我的客户端代码

gedit udp_client.c

并在文本编辑器中输入

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

int main()
{
    int udpSocket, portNum, nBytes;
    char buffer[1024] = "hello";
    struct sockaddr_in serverAddr;
    socklen_t addr_size;
    unsigned int alen;

    /*create UDP socket */
    udpSocket = socket(AF_INET, SOCK_DGRAM, 0); 

    /* Configure settings in address struct */
    serverAddr.sin_family = AF_INET;
    serverAddr.sin_port = htons(0);
    serverAddr.sin_addr.s_addr = inet_addr("192.168.1.1");
    memset(serverAddr.sin_zero, '\0', sizeof(serverAddr.sin_zero));

    addr_size = sizeof(serverAddr);

    while(1)
    {
         printf("sending %s\n", buffer);
         nBytes = strlen(buffer);
         sendto(udpSocket, buffer, nBytes, 0, (struct sockaddr *)&serverAddr, addr_size);
         sleep(1);
    }
return 0;
}

如果我的代码不是那么精致,我道歉。

1 个答案:

答案 0 :(得分:0)

好的,非常感谢大家的所有建议,但我确实有一些有用的代码。

我仍然不确定这是如何工作的,但对于初学者我选择的端口号不正确。根据Steve Summitt的说法,我使用Netcat检查了我的连接,当我查看端口0时,netcat会让我知道我不能选择低端口号。这有点令人困惑,因为我正在阅读的所有内容都说端口号从0开始。还有一个问题是尝试不使用过去常见的0-255端口,但现在是0-1023。我试图弄清楚我是否知道我可以使用哪些端口,而且我遇到了这个。

https://sort.veritas.com/public/documents/vie/7.3/aix/productguides/html/sfcfsha_config/apgs04s03.htm

虽然我不确定上下文是否仅在使用IPv6协议时?

我也找到了这个清单。

https://www.iana.org/assignments/service-names-port-numbers/service-names-port-numbers.xhtml

我想每台使用这些端口的机器上都有很多应用程序?

快速解决方案:我将端口设置为1024,忘记将客户端套接字绑定到客户端计算机网卡。我也改变了我做memset的方式(我以为我明白了,但我可能不会)

完整解决方案

当前设置: 我有两台Ubuntu机器通过一个简单的开关连接在一起。我称之为服务器(ubuntu 16.04)和客户端(ubuntu 14.04)。

我做的第一步是为每台机器分配静态IP(我认为这只推荐给我的服务器计算机,但我不知道如何在c中获取我的客户端的DHCP地址)。

在我的服务器计算机中,我打开了终端(ctrl + alt + t)

sudo ifconfig enp6s0 192.168.1.1 netmask 255.255.255.0

在客户端计算机中,我打开了终端并输入了

sudo ifconfig eth0 192.168.1.2 netmask 255.255.255.0

现在回到我键入的终端

中的服务器计算机
gedit udp_server.c

打开了一个文本编辑器

/************** UDP Server Code *****************/
#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <string.h>
#include <stdlib.h>
#include <arpa/inet.h>
#include <ctype.h>

int main()
{
    int udpSocket, nBytes;
    char buffer[5];
    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);

    /* Configure settings in address struct */
    serverAddr.sin_family = AF_INET;
    serverAddr.sin_port = htons(1024);
    serverAddr.sin_addr.s_addr = htonl(INADDR_ANY);
    memset(serverAddr.sin_zero, '\0', sizeof(serverAddr.sin_zero);

    /* Bind socket with address struct */
    bind(udpSocket, (struct sockaddr *)&serverAddr, sizeof(serverAddr));
    printf("bind complete port number %d\n", ntohs(serverAddr.sin_port));

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

    while(1)
    {
         nBytes = recvfrom(udpSocket, buffer, 5, (struct sockaddr *)&clientAddr, &addr_size);
         printf("any bytes %d\n", nBytes);
    }

return 0;
}

现在为我输入的客户端代码(在我的客户端计算机上)

gedit udp_client.c

打开了一个文本编辑器

/************ UDP client code **********/

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

int main()
{
     int udpSocket, portNum, nBytes;
     char buffer[1024] = "hello";
     struct sockaddr_in serverAddr, clientAddr;
     socklen_t addr_size;
     unsigned int alen;

     /* Create UDP socket */
     udpSocket = socket(AF_INET, SOCK_DGRAM, 0);

     /* Configure client settings in address struct */
     memset((char *)&clientAddr, 0, sizeof(clientAddr));
     clientAddr.sin_family = AF_INET;
     clientAddr.sin_addr.s_addr = inet_addr("192.168.1.2");
     clientAddr.sin_port = htons(0);

     if(bind(udpSocket, (struct sockaddr *)&clientAddr, sizeof(clientAddr)) < 0)
     {
         perror("bind failed");
         return 0;
     }

     printf("client bound");

     /* configure server settings in struct */
     memset((char *)&serverAddr, '0', sizeof(serverAddr));
     serverAddr.sin_family = AF_INET;
     serverAddr.sin_port = htons(1024);
     serverAddr.sin_addr.s_addr = inet_addr("192.168.1.1");

     printf("the socket ip addr is: %s\n", inet_ntoa(clientAddr.sin_addr));

     addr_size = sizeof(serverAddr);

     while(1)
     {
          sleep(2);
          nBytes = strlen(buffer);

          if(sendto(udpSocket, buffer, nBytes, 0, (struct sockaddr *)&serverAddr, sizeof(serverAddr)) == -1)
          {
                 perror("send to");
                 exit(1);
          }

          printf("sent %s\n", buffer);
     }

return 0;
}

一些额外的笔记

  • 我实际上不知道是否需要在客户端绑定我的套接字?我把它绑定到端口0,一切都工作了peachey。如果我尝试从服务器接收,我想可能会遇到问题?
  • 我还在研究如何思考港口的比喻
    • 我想知道IP地址是网卡地址(城市),端口号是该城市内的地址(任务,应用程序)。像许多人可以居住在一个城市一样,许多任务或程序可以驻留在一台机器上,每个人都可能希望与世界沟通。
  • 这只是最基本的信息(我不介绍其他内容,如connect(),send(),write(),sendmsg(),因为我不知道如何使用它们)
  • 希望这篇文章能让下一个人更轻松。