2015-06-09 83 views
1

我正在实现一个TFTP客户端(UDP套接字)。检测TFTP数据的传入端口?

目前我必须关闭Windows 8计算机上的整个防火墙,否则数据不会到达TFTP客户端。外出连接请求发生在端口69上,但来自TFTP服务器的第一个数据包在不同的随机端口上传回。所以我的问题是:如何确保TFTP客户端(作为应用程序)能够在防火墙打开的计算机上接收数据包?

当我在Visual Studio 2005中以调试模式运行TFTP客户端时,除非关闭防火墙,否则客户端不会接收数据包。我如何解决这个问题?

由于

UPDATE(代码)

void main(void) 
{ 
    unsigned short OPCODE = htons((unsigned short)1); 
    char* fileName = "thisfile.cnf.xml"; 
    WORD wVersionRequested; 
    WSADATA wsaData; 
    int err; 
    SOCKET sockfd; 
    int n; 
    char buf[256] = {0}; 
    int L; 
    struct sockaddr_in servaddr; 
    char recvline[1000]; 
    int rc; 

    wVersionRequested = MAKEWORD(2, 2); 
    err = WSAStartup(wVersionRequested, &wsaData); 
    memcpy(buf, &OPCODE, 2); 
    sprintf_s(&buf[2], 254, "%s%c%s%c", fileName, '\0', "octet", '\0'); 
    L = (int) strlen(fileName) + 9; 
    sockfd=socket(AF_INET,SOCK_DGRAM,0); 
    memset(&servaddr,0,sizeof(servaddr)); 
    servaddr.sin_family = AF_INET; 
    servaddr.sin_addr.s_addr=inet_addr("212.158.10.33"); 
    servaddr.sin_port=htons(69); 
    rc = sendto(sockfd,buf,L,0, (struct sockaddr *)&servaddr,sizeof(servaddr)); 

    while (1) 
    { 
     printf("Receive 1st packet...\n"); 
     /* This call gets blocked unless firewall is off */ 
     n=recvfrom(sockfd,recvline,1000,0,NULL,NULL); 
     printf("%d bytes received\n", n); 
     break; 
    } 
} 

回答

3

的TFTP协议具有以下流程:

  1. 客户端从一个随机选择的CTID端口到端口发送一个RRQWRQ请求69在服务器上:

    客户端:C TID ------>服务器:从随机选择STID端口69个

  2. 服务器回应客户的CTID:

    客户:CTID < ------服务器:STID

  3. 根据需要在客户端的CTID和服务器的STID之间发送该传输的所有后续数据包。

    客户:CTID < ----->服务器:STID

每台机器挑选自己的 TID端口将被发送到对方的目的地 TID端口的数据包。如上所述,CTID和STID由相应的机器选择,最好是随机选择的。在您的代码中,您没有为您的请求设置源端口,因此它是由操作系统随机选择的。对于您的传出数据包而言,这很好,但防火墙不知道入站数据包的来源。因此,您需要将您的套接字bind()连接到您可以在防火墙中打开的特定端口。否则,请检查您的防火墙设置,看看它是否有可用的规则,允许来自传出UDP数据包最近发送到的IP地址的入站UDP数据包或类似的规则。

+0

完全可以找到让操作系统随机选择源端口。您只需确保在防火墙中打开了所生成的端口。即使你使用'bind()',你仍然可以绑定到端口0来获得一个随机的端口分配,然后查询套接字来发现分配的端口,然后你可以相应地打开防火墙(甚至通过防火墙API自动打开) 。否则,您必须事先预留一个端口池,确保它们全部在防火墙中打开,并且只绑定到这些端口。 –