2015-10-27

Bendradarbiavimas tarp kelių .bat failų

Bat failai negali perduoti per tinklą bet kokios naudingos informacijos vienas kitam. Nėra socket'ų, na ir gerai, bet yra paprastas darbas su failais. Kurti ir skaityti .bat tekstinius failus yra labai paprasta. Užtenka tik įvykdyti komandą echo Text>file.txt ir file.txt . Duotame file.txt įvesime tekstą "Text". Perskaityti šią eilutę galima pasinaudojus komanda set /p var=<file.txt (po kintamojo var gausime eilutę su šiuo tekstu "Text").
Taigi galime perduoti informaciją tarp .bat failų. O jeigu šie failai bus patalpinti tinkle, tai jie tarpusavyje galės "bendrauti" skirtinguose kompiuteriuose.

Nedidelis kliento-serverio pavyzdys. Failas rexec_server.bat:

set checkFolder=\\IMP5\PUBLIC_RW
:loop
@ping -n 2 127.0.0.1 > nul
@if not exist "%checkFolder%\!cmd" goto loop
@call "%checkFolder%\!command.bat" > "%checkFolder%\!result"
@del "%checkFolder%\!cmd"
@goto loop

Failas rexec_client.bat:

@echo off
set checkFolder=\\IMP5\PUBLIC_RW

:mainloop
set /p c=^>
if "%c%"=="exit" exit
if "%c%"=="quit" exit
echo %c%>"%checkFolder%\!command.bat"
echo.>"%checkFolder%\!cmd"

:waitloop
ping -n 2 127.0.0.1 > nul
if exist "%checkFolder%\!cmd" goto waitloop
type "%checkFolder%\!result"
del "%checkFolder%\!result"
goto mainloop

Darbo pavyzdys:
Viskas vyksta taip: rexec_server.bat laukia iš kliento komandinės eilutės ir įvykdo jąją tame kompiuteryje, kuriame ji paleista. Su klientu bendraujama per leidžiamą aplanką \\IMP5\PUBLIC_RW (jums šį aplanką reiks pakeisti savuoju, jei norėsite paeksperimentuoti). Kad klientas ir serveris nesusimaišytų ir anksčiau laiko neperskaitytų failų, kurie šiuo metu jiems rašomi, buvo peržiūrėtos failų vėliavėlės, kurios reikalingos tik tam, kad įsitikinti, jog informacija jau pilnai išsaugota.
Ir pabaigai - internetinis .bat žaidimukas "kryžiukai-nuliukai".
Priminimas, kad prieš paleidžiant eilutėje set FLAG_DIR=\\IMP5\SHARED_RW reikia nurodyti savo leidžiamą aplanką (naudojant vieną aplanką galima žaisti ne vieną žaidimą).

Failas xo.bat:

@echo off
cls
set FLAG_DIR=\\IMP5\SHARED_RW

call :create_chars

:restart
echo Please wait...
call :sys_utils init "%0"
set cmdPrefix=$p%__PID%

rem  ------- connecting --------

call :sys_utils enter_critical_section
cls
call :sys_utils fetch_flag ready_to_play
if "%RESULT%"=="" (
  call :sys_utils set_flag ready_to_play %cmdPrefix%
  set symbol=X
  set symbol2=O
  set server=1
) else (
  set cmdPrefix=%RESULT%
  call :sys_utils set_flag %RESULT%_client_ready ---
  set symbol=O
  set symbol2=X
  set server=0
)
call :sys_utils leave_critical_section

if "%server%"=="0" goto client1
  call :wait_for_client
  call :sys_utils set_flag %cmdPrefix%_server_ready_too ---
  goto skipClient1
:client1
  call :wait_for_server
  if "%serverFailure%"=="1" goto restart
:skipClient1

rem  ------- connected --------

call :clear_field
if "%server%"=="1" (set curMode=your_turn) else (set curMode=enemy_turn)

:main_game_loop
  cls
  call :check_win
  call :render_field

  if "%winSymbol%"=="%symbol%" goto you_win
  if "%winSymbol%"=="%symbol2%" goto enemy_win
  
  if not "%curMode%"=="your_turn" goto skipTurn1
    echo.
    echo Your are "%symbol%"
    echo.
    set /p tmp=Please enter <nul
    if "%f1%"=="1" set /p tmp=1, <nul
    if "%f2%"=="2" set /p tmp=2, <nul
    if "%f3%"=="3" set /p tmp=3, <nul
    if "%f4%"=="4" set /p tmp=4, <nul
    if "%f5%"=="5" set /p tmp=5, <nul
    if "%f6%"=="6" set /p tmp=6, <nul
    if "%f7%"=="7" set /p tmp=7, <nul
    if "%f8%"=="8" set /p tmp=8, <nul
    if "%f9%"=="9" set /p tmp=9, <nul
    echo or 'q' for quit
    echo.
    set /p "tmp=Your turn: "

    if "%tmp%"=="q" goto quit_game
    if "%tmp%"=="Q" goto quit_game

    call set varName=%%f%tmp%%%
    if not "%varName%"=="%tmp%" goto main_game_loop
    call set f%tmp%=%symbol%

    call :sys_utils set_flag %cmdPrefix%_%symbol%_move f%tmp%
    set curMode=enemy_turn
    goto main_game_loop
  :skipTurn1

  if not "%curMode%"=="enemy_turn" goto skipTurn2
    echo.
    echo Waiting for another player
    :wait_for_player0
      set /p tmp=.<nul
      ping -n 2 127.0.0.1 > nul
      call :sys_utils fetch_flag %cmdPrefix%_%symbol2%_move
    if "%RESULT%"=="" goto wait_for_player0

    echo %RESULT%

    if "%RESULT%"=="q" goto other_player_quit

    call set %RESULT%=%symbol2%
    set curMode=your_turn
    goto main_game_loop
  :skipTurn2

goto main_game_loop

:quit_game
  call :sys_utils set_flag %cmdPrefix%_%symbol%_move q
exit

:other_player_quit
  cls
  echo Other player has left the game.
  echo Press 'Enter' to search for another one.
  pause > nul
goto restart

:you_win
  echo.
  echo You Win
  echo.
  echo Press 'Enter'
  pause > nul
goto restart

:enemy_win
  echo.
  echo You Lose
  echo.
  echo Press 'Enter'
  pause > nul
goto restart

:wait_for_client
  echo Waiting for client
  :wait_for_client1
    set /p tmp=.<nul
    ping -n 2 127.0.0.1 > nul
    call :sys_utils fetch_flag %cmdPrefix%_client_ready
  if "%RESULT%"=="" goto wait_for_client1
exit /b

:wait_for_server
  echo Waiting for server
  set serverFailure=0
  set /a waitCnt=4
  :wait_for_server1
    set /a waitCnt-=1
    if "%waitCnt%"=="0" (
      set serverFailure=1
      exit /b
    )
    set /p tmp=.<nul
    ping -n 2 127.0.0.1 > nul
    call :sys_utils fetch_flag %cmdPrefix%_server_ready_too
  if "%RESULT%"=="" goto wait_for_server1
exit /b

:clear_field
  set "f1=1"
  set "f2=2"
  set "f3=3"
  set "f4=4"
  set "f5=5"
  set "f6=6"
  set "f7=7"
  set "f8=8"
  set "f9=9"
exit /b


:create_chars

  set "charX0= #   # ^|"
  set "charX1=  # #  ^|"
  set "charX2=   #   ^|"
  set "charX3=  # #  ^|"
  set "charX4= #   # ^|"
  set "charX5=-------+"

  set "charO0=  ###  ^|"
  set "charO1= #   # ^|"
  set "charO2= #   # ^|"
  set "charO3= #   # ^|"
  set "charO4=  ###  ^|"
  set "charO5=-------+"

  set "charXW0=.#...#.^|"
  set "charXW1=..#.#..^|"
  set "charXW2=...#...^|"
  set "charXW3=..#.#..^|"
  set "charXW4=.#...#.^|"
  set "charXW5=-------+"

  set "charOW0=..###..^|"
  set "charOW1=.#...#.^|"
  set "charOW2=.#...#.^|"
  set "charOW3=.#...#.^|"
  set "charOW4=..###..^|"
  set "charOW5=-------+"

  for %%i in (1,2,3,4,5,6,7,8,9) do call :create_empty_char %%i

exit /b

:create_empty_char
  set "char%10=       ^|"
  set "char%11=       ^|"
  set "char%12=   %1   ^|"
  set "char%13=       ^|"
  set "char%14=       ^|"
  set "char%15=-------+"
exit /b

:check_win
  set winSymbol=.
  call :check3 1 2 3
  call :check3 4 5 6
  call :check3 7 8 9
  call :check3 1 4 7
  call :check3 2 5 8
  call :check3 3 6 9
  call :check3 1 5 9
  call :check3 3 5 7
exit /b

:check3
  call set tmp1=%%f%1%%%%f%2%%%%f%3%%
  call set tmp2=%%f%1%%%%f%1%%%%f%1%%
  if "%tmp1%"=="%tmp2%" (
    call set "winSymbol=%%f%1%%"
    call set "f%1=%%f%1%%W"
    call set "f%2=%%f%2%%W"
    call set "f%3=%%f%3%%W"
  )
exit /b

:render_field
  call :render_line %f1% %f2% %f3%
  call :render_line %f4% %f5% %f6%
  call :render_line %f7% %f8% %f9%
exit /b

:render_line
   call echo %%char%10%%%%char%20%%%%char%30%%
   call echo %%char%11%%%%char%21%%%%char%31%%
   call echo %%char%12%%%%char%22%%%%char%32%%
   call echo %%char%13%%%%char%23%%%%char%33%%
   call echo %%char%14%%%%char%24%%%%char%34%%
   call echo %%char%15%%%%char%25%%%%char%35%%
exit /b


rem ----------------- atom --------------
:sys_utils
goto %1
exit /b

:init
  if "%FLAG_DIR%"=="" set FLAG_DIR=.
  set UNIQ_BAT_ID=%COMPUTERNAME%_%USERNAME%_%~n2
  set /A CRITICAL_SECTION_LEVEL=0

  call :enter_critical_section
  call :test_flag --null-- $pid$
  set /A __PID=%RESULT%
  if [%__PID%]==[0] set /A __PID=10000000
  if [%__PID%]==[] set /A __PID=10000000
  if [%__PID%]==[99999999] set /A __PID=10000000
  set /A __PID=__PID+1
  call :set_flag --null-- $pid$ %__PID% 
  call :leave_critical_section

  set UNIQ_BAT_ID=%UNIQ_BAT_ID%_pid%__PID%
exit /b

:set_flag
  call :enter_critical_section
  echo %3>"%FLAG_DIR%\%2"
  call :leave_critical_section
exit /b

:remove_flag
  call :enter_critical_section
  if exist "%FLAG_DIR%\%2" del "%FLAG_DIR%\%2"
  call :leave_critical_section
exit /b

:fetch_flag
  call :enter_critical_section
  set "RESULT="
  if exist "%FLAG_DIR%\%2" (
    set /p RESULT=<"%FLAG_DIR%\%2"
    del "%FLAG_DIR%\%2"
  )
  call :leave_critical_section
exit /b

:test_flag
  call :enter_critical_section
  set "RESULT="
  if exist "%FLAG_DIR%\%2" set /p RESULT=<"%FLAG_DIR%\%2"
  call :leave_critical_section
exit /b

:enter_critical_section
  set /A CRITICAL_SECTION_LEVEL=CRITICAL_SECTION_LEVEL+1
  if not [%CRITICAL_SECTION_LEVEL%]==[1] exit /b

  set /A __WAIT_CNT=500

  :wait_enter_critical_section
  set /A __WAIT_CNT=__WAIT_CNT-1
  if [%__WAIT_CNT%]==[0] del "%FLAG_DIR%\$cs$_*"
  if exist "%FLAG_DIR%\$cs$_*" goto wait_enter_critical_section

  echo.>"%FLAG_DIR%\$cs$_%UNIQ_BAT_ID%"
  set /A __CNT=0
  for %%i in ( "%FLAG_DIR%\$cs$_*" ) do set /a __CNT=__CNT+1
  if [%__CNT%]==[1] goto all_right_1
    del "%FLAG_DIR%\$cs$_%UNIQ_BAT_ID%"
    goto wait_enter_critical_section
  :all_right_1
exit /b

:leave_critical_section
  set /A CRITICAL_SECTION_LEVEL=CRITICAL_SECTION_LEVEL-1
  if [%CRITICAL_SECTION_LEVEL%]==[0] del "%FLAG_DIR%\$cs$_%UNIQ_BAT_ID%"
exit /b

:EOF

Pasiremta: habrahabr.ru

Komentarų nėra:

Rašyti komentarą