2014-07-22 5 views
0

웹 서버에서 Hello-Request를받을 웹 서버를 작성 중입니다. Hello 응답을 보내야 만합니다. hello 응답을 보낸 후에는 명령 실행 모드로 들어갑니다. 여기에 제공된 명령이 클라이언트에 전송됩니다.tcl의 TCP 소켓 프로그래밍

여기 hello-request 서버가 수신 확인을 보내는 중입니다. 그래서 소켓이 닫히고 있습니다. 안녕하세요 - 응답을 보낼 때 연결이 닫힙니다 (클라이언트가 [RST, ACK]로 회신 중입니다). hello-request 패킷 자동 수신을 중지하고 서버가 닫힐 때까지 소켓을 열린 상태로 유지하는 방법.

proc dmePrompt {} { 
    puts -nonewline "DME#>" 
    flush stdout 
} 

proc sendResponseFor {sock msg} { 
    global uuid timeStamp 
    puts "Hello " 
    if {[dict get $msg Action] == "HELLOREQUEST"} {     
     set uuid [dict get $msg ID]  
     set timestamp "[clock format [clock seconds] -format "%D %H:%M:%S"] UTC"  
     #Construct hello response structure 
     set helloResp " 
       Action  {HELLORESPONSE member} 
       Body  {{\ 
           isAuthorized  {true member}\ 
           hostname   {DME1 member}\ 
           ipAddress   {$::ipAddr member}\ 
           timestamp   {$timestamp member}\ 
           token    {aabbccddeeff member}\ 
           newKey    {abcdqwertyuiops member}\ 
           redirect   {false member}\ 
           flags    {null member}\ 
           keepAliveInterval {1000 member}\ 
           forceInsecure  {false member}} object}\ 
       ID   {$uuid member}\ 
       TimeStamp {$timestamp member}\ 
       isError  {false member}" 

     set jsonResp [encodeJson $helloResp] 
     set dataLen [format %08X [expr [string length [getHexForAsciiChars $jsonResp]]/2]] 
     if {[info exists headerLen] && $headerLen == 8} { 
      append dataLen "00000000" 
     }   

     puts $sock "$dataLen$jsonResp" 
     flush $sock 
     enterCmdExecMode $sock 
    } 

} 
proc enterCmdExecMode {sock} { 
    set readData 1 
    while {1} { 
     dmePrompt 
     gets stdin cmd 
    }  
} 
proc readsock {sock} { 
    global buffer  
    if {[gets $sock request] < 0} { 
     close $sock 
    } else { 
     binary scan $request H* data 
     append buffer $data 

     #set dataLen [string range $buffer 0 7] 
     #set dataLen [expr (0x$dataLen + 8) * 2 -1] 
     set dataLen 703 
     if {[string length $buffer] < $dataLen} { 
      set readData 1 
     } else { 
      set hexData [string range $buffer 8 $dataLen] 
      set buffer [string range $buffer [expr $dataLen +1] end] 
      if {$::encryptionEnabled} { 
       set hexData [decryptAES 121301080D010518130E082007136412 $hexData]     
      } 
      set data [hexToString $hexData] 
      set msg [json::json2dict $data] 
      sendResponseFor $sock $msg           
     } 
    } 
} 
set server [socket -server serverOpen 33000] 
proc server_accept {sock addr port} { 
    puts "Connection request received from $addr $port" 
    fconfigure $sock -buffering none -translation binary 
    fileevent $sock readable [list readsock $sock]  
} 
socket -myaddr $ipAddr -server server_accept 33444 
dmePrompt 
set readData 0 
vwait readData 

답변

1

특별히 명백하게 잘못된 것은 없지만 비 블로킹 소켓을 사용하여 더 비동기적인 리더 코드를 작성해야합니다.

proc server_accept {sock addr port} { 
    puts "Connection request received from $addr $port" 
    fconfigure $sock -buffering none -translation binary -blocking 0 
    fileevent $sock readable [list readsock $sock]  
} 
proc readsock {sock} { 
    global buffer  
    if {[gets $sock request] < 0} { 
     if {[eof $sock]} { 
      close $sock 
     } 
     return 
    } 
    # No need to put the rest inside an “else” arm because of the “return” 

    ... 
} 

이도의 두 번째 서버 소켓이 당신의 코드에 의해 개설되고,하지만 당신은 그에 대한 코드의 나머지 부분을 표시하지 않는, 당신은 아마에 a bgerror handler 그래서 어떤 문제를 설정한다고 이벤트 처리가 완전히보고 됨 :

proc bgerror msg { 
    # Copy this immediately, as “clock format” is implemented in Tcl internally 
    set stackTrace $::errorInfo 
    puts stderr "[clock format [clock seconds]]: $msg\n$stackTrace" 
} 
+0

tcp FIN 패킷이 닫기를 호출하지 않고 전송 될 때 Tcl 소켓에 있음. – Surya

+0

누군가가 도착하자마자 데이터를 읽는 방법을 알려주십시오. 아무도 아니고 버퍼링을했습니다. 소켓에있는 데이터를 즉시 읽을 수있는 방법이 있습니까 ?? – Surya

+0

@Surya 미안하지만 첫 번째 의견을 이해할 수 없습니다. (그것은 긴 하루였습니다 ...) –