2014-04-22 2 views
1

C udp 소켓 샘플을 작성하고 있습니다. 이것은 클라이언트UDP 소켓 응답 없음

#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.The 클라이언트로 IP를 변경하면 서버의 응답 을 얻을 수 없습니다. 클라이언트는 recvfrom 함수에서 중지합니다.

아이디어가 있으십니까?

답변

1

Mac에서 실행 중이며 방화벽이 켜져 있습니까? 기본 필터링 규칙은 UDP를 보내고 응답 (클라이언트)을받을 수는 있지만 열려있는 소켓 (서버)에서 원치 않는 데이터 그램을 수신하는 것을 허용하지 않습니다.

소켓의 클라이언트 측이 반드시 bind(2) 일 필요는 없지만 코드는 괜찮습니다. 커널은 소스에 대해 다음으로 사용할 수있는 높은 번호의 포트를 할당합니다. 특정 클라이언트와 서버 간의 확장 대화를 계획하는 경우 클라이언트에서 connect(2)을 사용하는 것이 좋습니다.

또한 항상은 네트워크에서 수신 한 문자열을 명시 적으로 0으로 종료하려고합니다. 이렇게하지 않으면 끝없는 원격 악용의 원천이되었습니다.

+0

감사합니다. 예, Mac에서 실행 중입니다. 샘플을 펀칭하는 udp 구멍을 작성하고 싶습니다. 소켓의 클라이언트 측을 바인드합니다. 달성 방법? – Sid

+0

좋습니다. 이제 대답을 수락하는 법을 배워야합니다. –

+0

함수 연결을 사용하여 달성 할 수 있습니까? – Sid