UDP套接字无响应

时间:2014-04-22 02:37:54

标签: sockets udp

我正在写一个c udp socket示例。 这是客户端

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

int
main(int argc, char *argv[]) {
    if (argc < 3) {
        fprintf(stderr, "Usage: %s ip port\n", argv[0]);
        exit(1);
    }

    int sock;
    char *server_ip;
    unsigned short server_port;
    struct sockaddr_in cliAddr, serAddr;

    if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0)  {
        fprintf(stderr, "socket failed\n");
        exit(1);
    }

    server_ip = argv[1];
    server_port = atoi(argv[2]);

    memset(&cliAddr, 0, sizeof(cliAddr));
    cliAddr.sin_family = AF_INET;
    cliAddr.sin_addr.s_addr = htonl(INADDR_ANY);
    cliAddr.sin_port = htons(21152);

    if (bind(sock, (struct sockaddr *) &cliAddr, sizeof(struct sockaddr)) < 0) {
        fprintf(stderr, "bind failed\n");
        exit(1);
    }

    memset(&serAddr, 0, sizeof(serAddr));
    serAddr.sin_family = AF_INET;
    serAddr.sin_addr.s_addr = inet_addr(server_ip);
    serAddr.sin_port = htons(server_port);

    if (sendto(sock, "hello", 5, 0, (struct sockaddr *) (&serAddr), sizeof(serAddr)) == -1) {
        fprintf(stderr, "sendto failed\n");
        exit(1);
    }

    printf("send success\n");

    int n;
    char recvstr[50];
    if ((n = recvfrom(sock, &recvstr, 50, 0, NULL, NULL)) < 0) {
        fprintf(stderr, "recvfrom failed\n");
        exit(1);
    }

    printf("receive success: %s\n", recvstr);
    printf("from %s:%d\n", inet_ntoa(serAddr.sin_addr), ntohs(serAddr.sin_port));

    exit(0);
  }

这是服务器

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

int
main(int argc, char *argv[]) {
    if (argc < 2) {
        fprintf(stderr, "Usage: %s port\n", argv[0]);
        exit(1);
    }

    int sock, n;
    struct sockaddr_in servaddr, cliaddr;
    char recvstr[50];
    socklen_t cliaddrlen;

    if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
        fprintf(stderr, "socket failed\n");
        exit(1);
    }

    memset(&servaddr, 0, sizeof(servaddr));
    servaddr.sin_family = AF_INET;
    servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
    servaddr.sin_port = htons(atoi(argv[1]));

    if (bind(sock, (struct sockaddr *)&servaddr, sizeof(servaddr)) < 0) {
        fprintf(stderr, "bind failed\n");
        exit(1);
    }

    cliaddrlen = sizeof(cliaddr);
    if ((n = recvfrom(sock, recvstr, 50, 0, (struct sockaddr *) &cliaddr, &cliaddrlen)) < 0) {
        fprintf(stderr, "recvfrom failed\n");
        exit(1);
    }

    printf("client ip: %s, client port: %d\n", inet_ntoa(cliaddr.sin_addr), ntohs(cliaddr.sin_port));

    if (sendto(sock, "hello from server", 17, 0, (struct sockaddr *) &cliaddr, cliaddrlen) == -1) {
        fprintf(stderr, "sendto failed\n");
        exit(1);
    }

    printf("send success\n");

    exit(0);
}

当客户端和服务器位于本地时,它可以正常工作。 例如“./server 21151”和“./client 127.0.0.1 21151”。 服务器将获得:

client ip: 127.0.0.1, client port: 21152
send success

客户将得到:

send success
receive success: hello from serverB
from 127.0.0.1:21151

但是当我将ip更改为public ip时。客户端无法获得响应 从服务器。 客户端将停在函数recvfrom。

有什么想法吗?

1 个答案:

答案 0 :(得分:1)

让我猜一下 - 你在Mac上运行它并且防火墙已开启?默认过滤规则允许发送UDP并接收响应(客户端),但不允许在打开的套接字(服务器)上接收未经请求的数据报。

你的代码没问题,但你不一定需要bind(2)套接字的客户端。内核将为源分配下一个可用的高编号端口。如果您计划在给定客户端和服务器之间进行任何扩展对话,您可以考虑在客户端上使用connect(2)

始终希望明确地终止从网络接收的字符串。不这样做是无休止的远程攻击的源头。