2015-06-09 89 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自動打開) 。否則,您必須事先預留一個端口池,確保它們全部在防火牆中打開,並且只綁定到這些端口。 –