Компьютерный форум OSzone.net  

Компьютерный форум OSzone.net (http://forum.oszone.net/index.php)
-   AutoIt (http://forum.oszone.net/forumdisplay.php?f=103)
-   -   [решено] Коннект (http://forum.oszone.net/showthread.php?t=132061)

morgan1991 15-02-2009 15:37 1039154

Коннект
 
Помогите плиз сделать скрипт состоящий из клиента и сервера. Клиент состоит из окна и 6 кнопок по нажатию кнопки в зависимости от нажатой серверу отправляется символ а тот в свою очередь запускает функцию в зависимости от символа. Пытался делать сам но не конектит, только на локалке а на другой комп не конектит. + Конектиться он долже по паролю.

amel27 16-02-2009 05:09 1039726

Цитата:

Цитата morgan1991
Пытался делать сам но не конектит, только на локалке а на другой комп не конектит »

Поиграйте для начала готовыми примерами из справки для клиента (ф-ция TCPSend) и сервера (ф-ция TCPRecv). При запуске клиента на другом компе не забудьте задать $szIPADDRESS равным IP-адресу сервера (вместо макроса @IPAddress1).

morgan1991 16-02-2009 17:45 1040374

Спасибо

morgan1991 05-03-2009 16:56 1055793

Сделал так:

Сервер:


Код:

#RequireAdmin

;SERVER!! Start Me First !!!!!!!!!!!!!!!
#include <GUIConstants.au3>

; Set Some reusable info
; Set your Public IP address (@IPAddress1) here.

Dim $szIPADDRESS = @IPAddress1
Dim $nPORT = 33891

; Start The TCP Services
;==============================================

TCPStartUp()

; Create a Listening "SOCKET".
;  Using your IP Address and Port 33891.
;==============================================

$MainSocket = TCPListen($szIPADDRESS, $nPORT)

; If the Socket creation fails, exit.
If $MainSocket = -1 Then Exit

; Create a GUI for messages
;==============================================

; Initialize a variable to represent a connection
;==============================================

Dim $ConnectedSocket = -1

;Wait for and Accept a connection
;==============================================

Do
    $ConnectedSocket = TCPAccept($MainSocket)
Until $ConnectedSocket <> -1

; Get IP of client connecting

Dim $msg, $recv
; GUI Message Loop
;==============================================

While 1
  $msg = GUIGetMsg()

; GUI Closed
;--------------------

; Try to receive (up to) 2048 bytes
;----------------------------------------------------------------

    $recv = TCPRecv( $ConnectedSocket, 2048 )

; If the receive failed with @error then the socket has disconnected
;----------------------------------------------------------------

    If @error Then
        TCPShutDown()
        ShellExecute(@ScriptFullPath)
        Exit
    EndIf


; Update the edit control with what we have received
;----------------------------------------------------------------

    If $recv <> "" Then seporate($recv)
WEnd

If
$ConnectedSocket <> -1 Then TCPCloseSocket( $ConnectedSocket )

TCPShutDown()

Func seporate($reckkk)
    If $recv = "test" Then test()
    If $recv = "quit" Then quit()
EndFunc

Func
SocketToIP($SHOCKET)
    Local $sockaddr = DLLStructCreate("short;ushort;uint;char[8]")

    Local $aRet = DLLCall("Ws2_32.dll","int","getpeername","int",$SHOCKET, _
            "ptr",DLLStructGetPtr($sockaddr),"int_ptr",DLLStructGetSize($sockaddr))
    If Not @error And $aRet[0] = 0 Then
        $aRet = DLLCall("Ws2_32.dll","str","inet_ntoa","int",DLLStructGetData($sockaddr,3))
        If Not @error Then $aRet = $aRet[0]
    Else
        $aRet = 0
    EndIf

    $sockaddr = 0

    Return $aRet
EndFunc

Func
test()
        MsgBox(16, "шгнеш", "гшшгшлршгр")
EndFunc

Func
quit()
        MsgBox(16, "шгнеш", "гшшгшлршгр")
EndFunc

Клиент:

Код:

;CLIENT! Start Me after starting the SERVER!!!!!!!!!!!!!!!
; see TCPRecv example

#include <GUIConstants.au3>

; Start The TCP Services
;==============================================

TCPStartUp()

; Set Some reusable info
;--------------------------
; Set $szIPADDRESS to wherever the SERVER is. We will change a PC name into an IP Address

Dim $szIPADDRESS = InputBox("uuu", "Введите IP адрес сервера:")
Dim $nPORT = 33891

; Initialize a variable to represent a connection
;==============================================

Dim $ConnectedSocket = -1

;Attempt to connect to SERVER at its IP and PORT 33891
;=======================================================

$ConnectedSocket = TCPConnect($szIPADDRESS,$nPORT)

Dim $szData

; If there is an error... show it
If @error Then
    MsgBox(4112,"Error","TCPConnect failed with WSA error: " & @error)
; If there is no error loop an inputbox for data
;  to send to the SERVER.

Else
;Loop forever asking for data to send to the SERVER
    While 1
    ; InputBox for data to transmit
        $szData = InputBox("Data for Server",@LF & @LF & "Enter data to transmit to the SERVER:")

    ; If they cancel the InputBox or leave it blank we exit our forever loop
        If @error Or $szData = "" Then ExitLoop

    ; We should have data in $szData... lets attempt to send it through our connected socket.
        TCPSend($ConnectedSocket,$szData)

    ; If the send failed with @error then the socket has disconnected
    ;----------------------------------------------------------------

        If @error Then ExitLoop
    WEnd
EndIf

Дак вот как сделать так чтобы сервер мог тоже отвечать клиенту, а клиент как и сервер в зависимости от принятой команды выполнял определённую функцию?

morgan1991 09-03-2009 20:55 1059084

насколько я понял можно просто в файл сервера воткнуть всё из файла клиента и наооборот, потом поменять имена переменных и порт, и получится двусторонняя связь.
Но вот такой вопросик как сделать чтобы клиент мог конектиться по паролю? Или хотябы скажите как сервер может отсоеденить клиента от себя? И ещё как сделать чтобы можно было с нескольких компов приконектиться к серверу одновреммено?

morgan1991 12-03-2009 23:26 1062207

Так и не получилось у меня создать двустороннюю связь, помогите пожалуйста...

proxy 13-03-2009 02:16 1062311

что то подсказывает, что это autoit-у тяжело дастят....не думал попробовать сделать на файлах?
к примеру все обращение передовать через ини или базу какую нить...

amel27 13-03-2009 13:03 1062624

Цитата:

Цитата morgan1991
Так и не получилось у меня создать двустороннюю связь »

простой двусторонний чат на базе примера из справки:
Код:

#include <GUIConstantsEx.au3>
Opt('MustDeclareVars', 1)

Example()

Func Example()
    Local $szIPLocal  = @IPAddress1
    Local $szIPRemote = @IPAddress1
    Local $LocalPort  = 33892
    Local $RemotePort = 33891

    Local $MainSocket, $GOOEY, $InputSocket=-1, $OutputSocket=-1, $szIP_Accepted
    Local $Bttn1, $Bttn2, $Edit1, $Edit2
    Local $msg, $recv, $szData

    TCPStartup()
    $MainSocket = TCPListen($szIPLocal, $LocalPort)
    If $MainSocket = -1 Then Exit

    $GOOEY = GUICreate("My Server (IP: " & $szIPLocal & ")", 300, 250)
    $Edit1 = GUICtrlCreateEdit("", 10, 10, 280, 180)
    $Edit2 = GUICtrlCreateEdit("", 10, 190, 280, 20, 0)
    $Bttn1 = GUICtrlCreateButton("Connect!", 10, 217, 120)
    $Bttn2 = GUICtrlCreateButton("Send Text", 170, 217, 120)
    GUISetState()

    While 1
        $msg = GUIGetMsg()
        If $msg = $GUI_EVENT_CLOSE Then ExitLoop
        If
$msg = $Bttn1 Then
            If
GUICtrlRead($Bttn1)="Connect!" Then
                $OutputSocket = TCPConnect($szIPRemote, $RemotePort)
                If @error Then
                    MsgBox(4112, "Error", "TCPConnect failed with WSA error: " & @error)
                Else
                    GUICtrlSetData($Bttn1, "Disconnect!")
                EndIf
            Else
                If $OutputSocket<> -1 Then TCPCloseSocket($OutputSocket)
                $OutputSocket=-1
                GUICtrlSetData($Bttn1, "Connect!")
            EndIf
        EndIf
        If $msg = $Bttn2 Then
            $szData = GUICtrlRead($Edit2)
            If $OutputSocket<>-1 And $szData<>"" Then
                TCPSend($OutputSocket, $szData)
                GUICtrlSetData($Edit1, $szIPLocal &" > "& $szData & @CRLF & GUICtrlRead($Edit1))
            EndIf
        EndIf

        $recv = TCPRecv($InputSocket, 2048)
        If @error Then
            $InputSocket = TCPAccept($MainSocket)
            If $InputSocket <> -1 Then $szIP_Accepted = SocketToIP($InputSocket)
        Else
            If $recv<>"" Then GUICtrlSetData($Edit1, $szIP_Accepted &" > "& $recv & @CRLF & GUICtrlRead($Edit1))
        EndIf
    WEnd

    If $InputSocket <> -1 Then TCPCloseSocket($InputSocket)
    If $OutputSocket<> -1 Then TCPCloseSocket($InputSocket)
    TCPShutdown()
EndFunc  ;==>Example

Func SocketToIP($SHOCKET)
    Local $sockaddr, $aRet
    $sockaddr = DllStructCreate("short;ushort;uint;char[8]")

    $aRet = DllCall("Ws2_32.dll", "int", "getpeername", "int", $SHOCKET, _
            "ptr", DllStructGetPtr($sockaddr), "int*", DllStructGetSize($sockaddr))
    If Not @error And $aRet[0] = 0 Then
        $aRet = DllCall("Ws2_32.dll", "str", "inet_ntoa", "int", DllStructGetData($sockaddr, 3))
        If Not @error Then $aRet = $aRet[0]
    Else
        $aRet = 0
    EndIf
    $sockaddr = 0

    Return $aRet
EndFunc  ;==>SocketToIP


morgan1991 13-03-2009 15:35 1062783

amel27, спасибо

morgan1991 14-03-2009 21:58 1063993

Такая вот проблемка конектюсь к серверу, потом одновременно конектюсь с другого компа и у второго клиента с виду всё норм но на самом деле сервер его запросы не обрабатывает, а первый нормально работает. Дак вот такой вопросик: как сделать чтобы конектиться к серверу одновременно мог только один человек? И ещё как сервер может отсоеденить от себя клиент который уже приконектился?

morgan1991 15-03-2009 14:06 1064457

И вот по ходу ещё вопросик возник:
Почему не передаются длинные значения? Например 40 слов разделённые "|". Каждое слово гдето из 8 символов. Это както можно поправить?

morgan1991 18-03-2009 00:09 1066777

Или хотябы скажите ктонибудь как передать одномерный массив?

proxy 18-03-2009 02:29 1066836

Цитата:

Цитата morgan1991
Почему не передаются длинные значения? »

тогда ж можно передовать по частям...


это к той прожке, что инфо собирает с компа собираетесь прикрутить?
если да - то гараздо проще на файлах.
даже стоит попробовать sql, если не ошибаюсь в udf-ах по ней есть.

morgan1991 18-03-2009 08:33 1066923

Цитата:

Цитата proxy
это к той прожке, что инфо собирает с компа собираетесь прикрутить? »

нет...
Цитата:

Цитата proxy
даже стоит попробовать sql, если не ошибаюсь в udf-ах по ней есть. »

Пробовал с бд круить по хэлпу, но.... там стока всего...
По частям тоже не понятно, можно передавать номер части через |, но в это время серверу может передаться чёнить ещё, да и как сделать чтобы сервер ждал пока придёт определённая часть?

proxy 18-03-2009 08:45 1066937

с серваками хз ))))
а вот на файлах думаю легко можно сделать, sql еще не смотрел, но как минимум тот же txt легко покатит )

morgan1991 18-03-2009 15:48 1067334

Цитата:

Цитата proxy
а вот на файлах думаю легко можно сделать »

т.е. можно файлик передать?
А как?

amel27 18-03-2009 16:43 1067387

Цитата:

Цитата morgan1991
Почему не передаются длинные значения? Например 40 слов разделённые "|". Каждое слово гдето из 8 символов. »

странно - передал без проблем по сетке 100 слов по 9 букв с разделителем, т.е. 500 знаков :dont-know

Цитата:

Цитата morgan1991
Такая вот проблемка конектюсь к серверу, потом одновременно конектюсь с другого компа и у второго клиента с виду всё норм но на самом деле сервер его запросы не обрабатывает, а первый нормально работает. Дак вот такой вопросик: как сделать чтобы конектиться к серверу одновременно мог только один человек? »

например так: сервер - создает сокет с очередью длинной 1 (3-й параметр TCPListen), принимает только первое соединение, открывает/закрывает только весь сокет целиком. Клиент - делает попытку коннекта и при успехе сразу делает попытку второго коннекта, забивая очередь... тогда любой "третий" получит "отлуп", пробовал - работает

morgan1991 18-03-2009 17:38 1067431

Цитата:

Цитата amel27
странно - передал без проблем по сетке 100 слов по 9 букв с разделителем, т.е. 500 знаков »

сори, у меня ошибка была.
Цитата:

Цитата amel27
создает сокет с очередью длинной 1 (3-й параметр TCPListen) »

а если поставить 0, то будет конектиться только 1 человек? Или будет без ограничений?

amel27 19-03-2009 02:06 1067852

Цитата:

Цитата morgan1991
если поставить 0, то будет конектиться только 1 человек? Или будет без ограничений? »

этот параметр влияет на длину очереди неподтвержденных запросов на соединение, а не на количество соединений... у меня получилось, что 0 и 1 дают одинаковую длину =1, т.е. если сервер подтверждает только один запрос (при этом он удаляется из очереди), все остальные будут падать в очередь до тех пор, пока она не заполнится, после этого все остальные попытки будут сервером отвергаться

amel27 19-03-2009 09:55 1068024

мысль пришла - сервер может сам отрубить свою очередь таким же образом,
предыдущий вариант с ограничителем:
Код:

#include <GUIConstantsEx.au3>
Opt('MustDeclareVars', 1)

Example()

Func Example()
    Local $szIPLocal  = @IPAddress1
    Local $szIPRemote = @IPAddress1
    Local $LocalPort  = 33890
    Local $RemotePort = 33891

    Local $TempSocket, $MainSocket=-1, $GOOEY, $InputSocket=-1, $OutputSocket=-1, $szIP_Accepted
    Local $Bttn1, $Bttn2, $Edit1, $Edit2
    Local $msg, $recv, $szData

    TCPStartup()

    $GOOEY = GUICreate("My Server (IP: " & $szIPLocal & ")", 300, 250)
    $Edit1 = GUICtrlCreateEdit("", 10, 10, 280, 180)
    $Edit2 = GUICtrlCreateEdit("", 10, 190, 280, 20, 0)
    $Bttn1 = GUICtrlCreateButton("Connect!", 10, 217, 120)
    $Bttn2 = GUICtrlCreateButton("Send Text", 170, 217, 120)
    GUISetState()

    While 1
        If $MainSocket = -1 Then $MainSocket = TCPListen($szIPLocal, $LocalPort, 1)
        If $MainSocket <> 1 Then
            If
$InputSocket= -1 Then
                $InputSocket = TCPAccept($MainSocket)
                If $InputSocket <> -1 Then TCPConnect($szIPLocal, $LocalPort)
            Else
                $szIP_Accepted = SocketToIP($InputSocket)
                $recv = TCPRecv($InputSocket, 2048)
                If @error Then
                    TCPCloseSocket($InputSocket)
                    TCPCloseSocket($MainSocket )
                    $MainSocket = -1
                    $InputSocket= -1
                Else
                    If $recv<>"" Then GUICtrlSetData($Edit1, $szIP_Accepted &" > "& $recv & @CRLF & GUICtrlRead($Edit1))
                EndIf
            EndIf
        EndIf

        $msg = GUIGetMsg()
        If $msg = $GUI_EVENT_CLOSE Then ExitLoop
        If $msg = $Bttn1 Then
            If GUICtrlRead($Bttn1)="Connect!" Then
                $OutputSocket = TCPConnect($szIPRemote, $RemotePort)
                If @error Then
                    MsgBox(4112, "Error", "TCPConnect failed with WSA error: " & @error)
                Else
                    GUICtrlSetData($Bttn1, "Disconnect!")
                EndIf
            Else
                If $OutputSocket<> -1 Then TCPCloseSocket($OutputSocket)
                $OutputSocket=-1
                GUICtrlSetData($Bttn1, "Connect!")
            EndIf
        EndIf

        If $msg = $Bttn2 Then
            $szData = GUICtrlRead($Edit2)
            If $OutputSocket<>-1 And $szData<>"" Then
                TCPSend($OutputSocket, $szData)
                GUICtrlSetData($Edit1, $szIPLocal &" > "& $szData & @CRLF & GUICtrlRead($Edit1))
            EndIf
        EndIf
    WEnd

    If $InputSocket <> -1 Then TCPCloseSocket($InputSocket)
    If $OutputSocket<> -1 Then TCPCloseSocket($InputSocket)
    If $MainSocket  <> -1 Then TCPCloseSocket($MainSocket)
    TCPShutdown()
EndFunc  ;==>Example

Func SocketToIP($SHOCKET)
    Local $sockaddr, $aRet
    $sockaddr = DllStructCreate("short;ushort;uint;char[8]")

    $aRet = DllCall("Ws2_32.dll", "int", "getpeername", "int", $SHOCKET, _
            "ptr", DllStructGetPtr($sockaddr), "int*", DllStructGetSize($sockaddr))
    If Not @error And $aRet[0] = 0 Then
        $aRet = DllCall("Ws2_32.dll", "str", "inet_ntoa", "int", DllStructGetData($sockaddr, 3))
        If Not @error Then $aRet = $aRet[0]
    Else
        $aRet = 0
    EndIf
    $sockaddr = 0

    Return $aRet
EndFunc  ;==>SocketToIP


morgan1991 05-04-2009 00:25 1084375

Скажите пожалуйста, а можно ли передавать файлы от клиента к серверу?

amel27 06-04-2009 09:31 1085399

в справке TCPSend/TCPRecv сказано, что бинарные данные тоже поддерживаются - значит можно
... интересно, а чем простое копирование не устраивает?

morgan1991 09-04-2009 01:55 1088488

Т.е. нужно превратить файл в бинарные данные, а потом обратно? А можно поподробнее?

morgan1991 09-04-2009 15:12 1088912

Сделал такой скриптик,

Клиент делает следующее:
Код:

$statdata = FileOpen ("14.txt", 16 );открываем файл в бинарном режиме
$ReadStatdata = FileRead($statdata);читаем файл
$HexStatdata=String ($ReadStatdata);переводим в шестнадцатиричный текст
FileClose ($statdata);закрываем файл

Потом передаём данные серверу, потом на сервере выполняем это:
Код:

$BinStatdata=Binary ($HexStatdata);обратно переводим их шестнадцатиричного в бинарный
$statdata2 = FileOpen ("15.txt", 2+16);открываем файл в бинарном режиме + режим записи
FileWrite ( $statdata2, $BinStatdata);пишим в файл изменённые данные
FileClose ($statdata2);закрываем файл

Но как теперь реализовать процент загрузки? + Процент загрузки должен видеть только сервер.

morgan1991 09-04-2009 16:17 1088979

Цитата:

Цитата morgan1991
Сделал такой скриптик, »

Не прокатил такой скрипт, через него можно передавать файлы только размером не более 250 к/байт.
Помогите пожалуйста, каким образом всётаки можно передать файл от клиента к серверу?

amel27 10-04-2009 13:42 1089881

Цитата:

Цитата morgan1991
каким образом всётаки можно передать файл от клиента к серверу? »

Не так все просто - тут нужно подобрать оптимальный для себя протокол обмена - команды, данные, подтверждения и т.д. Вариантов куча - все зависит от задачи. Вот пример односторонней передачи данных (без подтверждения) - сначала имя файла, размер, потом данные, при ошибке сессия сбрасывается.

сервер:
Код:

Global $iSocket = 33890
Global $hSocket = -1

TCPStartup()
$MainSocket = TCPListen("127.0.0.1", $iSocket, 1)
If $MainSocket<0 Then Exit MsgBox(16, "TCP Error", "Unable to intialize socket.")

$tsCTR = DllStructCreate("char Path[256];uint64 Size") ; управляющая структура копирования файла
$izCTR = DllStructGetSize($tsCTR)                      ; размер структуры
$ipCTR = DllStructGetPtr ($tsCTR)                      ; указатель
$tbCTR = DllStructCreate("byte["& $izCTR &"]", $ipCTR) ; сериализованная структура (в бинарном виде)

While 1
    If $hSocket<0 Then
        $hSocket = TCPAccept($MainSocket)
        If $hSocket<0 Then ContinueLoop
        ; Получаем инфу о файле - назначение и размер
        $bData = Binary("")
        Do
            $bData &= TCPRecv($hSocket, 1, 1)
            If @error Then
                TCPCloseSocket($hSocket)
                $hSocket=-1
                ConsoleWrite("Ошибка получения параметров файла! Операция отменена." &@CRLF)
                ContinueLoop 2
            EndIf
        Until BinaryLen($bData)=$izCTR
        ; Считываем параметры
        DllStructSetData($tbCTR, 1, $bData)
        $sFile = DllStructGetData($tsCTR, "Path")
        $iFile = DllStructGetData($tsCTR, "Size")
        ; Создание файла
        $hFile = FileOpen($sFile, 2+16)
        If $hFile<0 Then
            TCPCloseSocket($hSocket)
            $hSocket=-1
            ConsoleWrite("Ошибка создания файла! Операция отменена." &@CRLF)
            ContinueLoop
        EndIf
        ; Процесс копирования данных
        $bData = Binary("")
        $zData = 0
        While $zData<$iFile
            $bData = TCPRecv($hSocket, 65536, 1)
            If @error Then
                TCPCloseSocket($hSocket)
                FileClose($hFile)
                ConsoleWrite("Соединение прервано! Операция отменена." &@CRLF)
                ContinueLoop 2
            EndIf
            $zData += BinaryLen($bData)
            If FileWrite($hFile, $bData)=0 Or $zData>$iFile Then
                TCPCloseSocket($hSocket)
                FileClose($hFile)
                ConsoleWrite("Неустранимая ошибка при копировании! Операция отменена." &@CRLF)
                ContinueLoop 2
            EndIf
        WEnd

        FileClose($hFile)
        ConsoleWrite("Файл успешно скопирован! ("& $sFile &")" &@CRLF)
    EndIf
WEnd

клиент:
Код:

Global $hSocket = -1
Global $sServer = "127.0.0.1"
Global $iServer = 33890

Global $sFileFrom = "d:\MyGame.ISO"          ; файл-источник на клиенте (ЧТО)
Global $sFileTo  = "c:\InBox\YourGame.ISO"  ; файл-приемник на сервере (КУДА)

TCPStartup()
_TCP_FileSend($sServer, $iServer, $sFileFrom, $sFileTo)
TCPShutdown()

Func _TCP_FileSend($server, $port, $FileFrom, $FileTo)
    Local $hSocket = TCPConnect($server, $port)
    If $hSocket = -1 Then Return SetError(1, 0, False)

    Local $hFile = FileOpen($FileFrom, 16)
    Local $zFile = FileGetSize($FileFrom), $bData, $zData
    If $hFile<0 Then Return SetError(3, 1, False)

    Local $tsCTR = DllStructCreate("char Path[256];uint64 Size")
    Local $izCTR = DllStructGetSize($tsCTR)
    Local $ipCTR = DllStructGetPtr ($tsCTR)
    Local $tbCTR = DllStructCreate("byte["& $izCTR &"]", $ipCTR)

    DllStructSetData($tsCTR, "Path", $sFileTo)
    DllStructSetData($tsCTR, "Size", $zFile)

    TCPSend($hSocket, DllStructGetData($tbCTR, 1))
    If @error Then Return SetError(2, 1, False)

    Local $iProgress = 0
    ProgressOn("Copy Progress", "Increments every 65536 bytes", "0 percent")

    While 1
        $bData = FileRead($hFile, 65536)
        If @error<0 Then ExitLoop
        If
@error>0 Then Return SetError(3, 2, False)

        $zData += BinaryLen($bData)
        TCPSend($hSocket, $bData)
        If @error Then Return SetError(2, 2, False)

        $iProgress = $zData/$zFile*100
        ProgressSet($iProgress, StringFormat("Copied %-2i\% percent...", $iProgress))
    WEnd

    ProgressOff()
    FileClose($hFile)
    TCPCloseSocket($hSocket)
    Return True
EndFunc


morgan1991 10-04-2009 15:36 1090024

Спасибо огромное, буду разбираться.

morgan1991 11-05-2009 23:31 1115849

Скажите ещё пожалуйста, возможно ли сделать так чтобы к одному скрипту могли приконнектиться неограниченное колличество человек? + должна быть двух сторонняя связь... Возможно это очень сложно, тогда хотябы подскажите как это работает, а я уже сам постараюсь собрать программку.

morgan1991 13-05-2009 16:48 1117482

Додумался сам, вот что получилось:

Сервер:
Код:

#include <GUIConstantsEx.au3>

Global $IPAdress = @IPAddress1, $port = 3391, $ConnectedSocket[50], $szIP_Accepted, $i, $msg, $all_user = 50

TCPStartup()

$MainSocket = TCPListen($IPAdress, $port)
If $MainSocket = -1 Then Exit MsgBox(16, "error", "$MainSocket = " & $MainSocket)

; Create a GUI for messages
;==============================================

$GOOEY = GUICreate("My Server (IP: " & $IPAdress & ")", 300, 200)
$edit = GUICtrlCreateEdit("Мой сервер версия 1.0.0.1", 10, 10, 280, 180)
GUICtrlSetState($edit, $GUI_DISABLE)
GUISetState()

For $i = 1 To $all_user - 1 Step + 1
    $ConnectedSocket[$i] = -1
Next

While
1
    For $i = 1 To $all_user - 1 Step + 1
        $msg = GUIGetMsg()
        If $msg = $GUI_EVENT_CLOSE Then Exit
        If
$ConnectedSocket[$i] = -1 Then
            $ConnectedSocket[$i] = TCPAccept($MainSocket)
            If $ConnectedSocket[$i] <> -1 Then GUICtrlSetData($edit, GUICtrlRead($edit) & @CRLF & "ID = " & $i & " подключен")
        EndIf
        $recv = TCPRecv($ConnectedSocket[$i], 2048)
        If @error And $ConnectedSocket[$i] <> -1 Then
            $ConnectedSocket[$i] = -1
            GUICtrlSetData($edit, GUICtrlRead($edit) & @CRLF & "ID = " & $i & " отключен!")
        EndIf
        If
$recv <> "" And Not @error Then GUICtrlSetData($edit, _
                GUICtrlRead($edit) & @CRLF & "ID = " & $i & " IP = " & SocketToIP($ConnectedSocket[$i]) & " > " & $recv)
    Next
WEnd

Func
SocketToIP($SHOCKET)
    Local $sockaddr, $aRet

    $sockaddr
= DllStructCreate("short;ushort;uint;char[8]")

    $aRet = DllCall("Ws2_32.dll", "int", "getpeername", "int", $SHOCKET, _
            "ptr", DllStructGetPtr($sockaddr), "ptr", DllStructGetSize($sockaddr))
    If Not @error And $aRet[0] = 0 Then
        $aRet = DllCall("Ws2_32.dll", "str", "inet_ntoa", "int", DllStructGetData($sockaddr, 3))
        If Not @error Then $aRet = $aRet[0]
    Else
        $aRet = 0
    EndIf

    $sockaddr = 0

    Return $aRet
EndFunc  ;==>SocketToIP

Клиент:
Код:

#include <GUIConstantsEx.au3>

Opt('MustDeclareVars', 1)

Global $ConnectedSocket = -1, $szData
Global $szIPADDRESS = "10.10.14.153"
Global $nPORT = 3391

TCPStartup()

$ConnectedSocket = TCPConnect($szIPADDRESS, $nPORT)

If @error Then
    MsgBox(4112, "Error", "TCPConnect failed with WSA error: " & @error)
Else
    While
1
        $szData = InputBox("Data for Server", @LF & @LF & "Enter data to transmit to the SERVER:")
        If @error Or $szData = "" Then ExitLoop

        TCPSend($ConnectedSocket, $szData)
        If @error Then ExitLoop MsgBox(4112, "Error", "TCPConnect failed with WSA error: " & @error)
    WEnd
EndIf

Только вот эти функции для определения IP, не одна не работают:

Первая:
Код:

Func SocketToIP($SHOCKET)
    Local $sockaddr, $aRet

    $sockaddr
= DllStructCreate("short;ushort;uint;char[8]")

    $aRet = DllCall("Ws2_32.dll", "int", "getpeername", "int", $SHOCKET, _
            "ptr", DllStructGetPtr($sockaddr), "ptr", DllStructGetSize($sockaddr))
    If Not @error And $aRet[0] = 0 Then
        $aRet = DllCall("Ws2_32.dll", "str", "inet_ntoa", "int", DllStructGetData($sockaddr, 3))
        If Not @error Then $aRet = $aRet[0]
    Else
        $aRet = 0
    EndIf

    $sockaddr = 0

    Return $aRet
EndFunc  ;==>SocketToIP

Вторая:
Код:

Func SOCKET2IP($SHOCKET)
Local $sockaddr = DLLStructCreate("short;ushort;uint;char[8]")

  $a = DLLCall("Ws2_32.dll","int","getpeername","int",$SHOCKET,"ptr",DLLStructGetPtr($sockaddr), _
                                            "int_ptr",DLLStructGetSize($sockaddr))
  If Not @error And $a[0] = 0 Then
      $a = DLLCall("Ws2_32.dll","str","inet_ntoa","int",DLLStructGetData($sockaddr,3))
      If Not @error Then $a = $a[0]
  Else
      $a = 0
  EndIf

    ; release Struct not really needed as it is a local
  $sockaddr = 0

  Return $a
EndFunc  ;==>SOCKET2IP

Помогите пожалуйста разобраться с этими функциями. Почему они не работают? Я в DLL 0.
И ещё всётаки как сделать двухстороннюю связь не открывая второго порта? Это вне моего понимания, приведу пример:
сервер голосового чата Ventrilo установлен на компьютере IP адрес которого виден из вне, а клиент коннектится к серверу с компьютера IP адрес которого виден только из локальной сети, дак каким же образом они обмениваются данными если сервер физически не сможет приконнектиться к клиенту т.к. его IP адрес не виден из вне? примерно тоже самое хочется сделать на Autoit.
Заранее спасибо!

morgan1991 14-05-2009 16:59 1118435

Я сделал сам двух стороннюю связь с неограниченным колличеством клиентов.
Но так и не понял как же всётаки работают все сервера игр, icq, и т.п. ?
В моём примере оба компьютера должны видеть IP адреса друг друга, если этого не происходит, то связь обрывается, т.к. двухсторонняя связь будет физически невозможна.
И ещё вопросик такой, функции которые я приводил в пример не работают, почемуто. Ответьте ктонибудь пожалуйста, а то сам с собой разговариваю... )

Клиент:

Код:

#include <GUIConstantsEx.au3>
#include <Misc.au3>

If _Singleton("connecter", 1) = 0 Then
    MsgBox(0, "Ошибка!", "Запуск двух копий программы запрещён!")
    Exit
EndIf

Global
$ConnectedSocket = -1, $szData
Global $szIPADDRESS = "89.108.114.19"
Global $nPORT = 3391, $count_time = 0

TCPStartup()

$MainSocket = TCPListen(@IPAddress1, 3392)
If $MainSocket = -1 Then Exit MsgBox(16, "error", "$MainSocket = " & $MainSocket)

$ConnectedSocket = TCPConnect($szIPADDRESS, $nPORT)

If @error Then
    MsgBox(4112, "Error", "TCPConnect failed with WSA error: " & @error)
    Exit
Else

    TCPSend($ConnectedSocket, @IPAddress1)
    If @error Then Exit MsgBox(4112, "Error", "IP addres not sending WSA error: " & @error)
    Do
        $ConnectedSocket2 = TCPAccept($MainSocket)
        $count_time += 1
    Until $ConnectedSocket2 <> -1 Or $count_time = 100
    If $count_time > 99 Then  Exit MsgBox(4112, "Error", "Время ожидания ответа от сервера истекло!")
    While 1
        $szData = InputBox("Data for Server", @LF & @LF & "Enter data to transmit to the SERVER:")
        If @error Or $szData = "" Then Exit

        TCPSend($ConnectedSocket, $szData)
        If @error Then Exit MsgBox(4112, "Error", "Error sending data WSA error: " & @error)
    WEnd
EndIf

Сервер:

Код:

#include <GUIConstantsEx.au3>

Global $IPAdress = @IPAddress1, $port = 3391, $nPORT = 3392, $ConnectedSocket[50], $szIP_Accepted, $i, $msg, $all_user = 50
Global $szIPADDRESS[50], $ConnectedSocket2[50], $temp = 0

TCPStartup()

$MainSocket = TCPListen($IPAdress, $port)
If $MainSocket = -1 Then Exit MsgBox(16, "error", "$MainSocket = " & $MainSocket)

; Create a GUI for messages
;==============================================

$GOOEY = GUICreate("My Server (IP: " & $IPAdress & ")", 300, 200)
$edit = GUICtrlCreateEdit("Мой сервер версия 1.0.0.1", 10, 10, 280, 180)
GUICtrlSetState($edit, $GUI_DISABLE)
GUISetState()

For $i = 1 To $all_user - 1 Step + 1
    $ConnectedSocket[$i] = -1
Next
$ii = 1
While 1
    For $i = 1 To $ii Step + 1
        $msg = GUIGetMsg()
        If $msg = $GUI_EVENT_CLOSE Then Exit
        If
$ii < $all_user Or $ii = $all_user Then
            If
$ConnectedSocket[$i] = -1 Then
                $ConnectedSocket[$i] = TCPAccept($MainSocket)
                If $ConnectedSocket[$i] <> -1 Then
                    While
$temp = 0
                        $recv = TCPRecv($ConnectedSocket[$i], 2048)
                        If @error Then
                            $szIPADDRESS[$i] = "error"
                            $temp = 1
                        EndIf
                        If $recv <> "" Then
                            $szIPADDRESS[$i] = $recv
                            $temp = 1
                        EndIf
                    WEnd
                    If $szIPADDRESS[$i] <> "error" Then
                        $ConnectedSocket2[$i] = TCPConnect($szIPADDRESS[$i], $nPORT)
                        If @error Then
                            TCPCloseSocket($ConnectedSocket[$i])
                            $ConnectedSocket2[$i] = -1
                            $ConnectedSocket[$i] = -1
                            GUICtrlSetData($edit, GUICtrlRead($edit) & @CRLF & "Связь с новым ID потеряна!")
                        Else
                            GUICtrlSetData($edit, GUICtrlRead($edit) & @CRLF & "ID = " & $i & " подключен")
                            $ii += 1
                        EndIf
                    EndIf
                EndIf
            EndIf
        EndIf
        $recv = TCPRecv($ConnectedSocket[$i], 2048)
        If @error And $ConnectedSocket[$i] <> -1 Then
            $ConnectedSocket[$i] = -1
            GUICtrlSetData($edit, GUICtrlRead($edit) & @CRLF & "ID = " & $i & " отключен!")
        EndIf
        If $recv <> "" And Not @error Then GUICtrlSetData($edit, _
                GUICtrlRead($edit) & @CRLF & "ID = " & $i & " IP = " & $szIPADDRESS[$i] & " > " & $recv)
    Next
WEnd

Func SocketToIP($SHOCKET)
    Local $sockaddr, $aRet

    $sockaddr = DllStructCreate("short;ushort;uint;char[8]")

    $aRet = DllCall("Ws2_32.dll", "int", "getpeername", "int", $SHOCKET, _
            "ptr", DllStructGetPtr($sockaddr), "ptr", DllStructGetSize($sockaddr))
    If Not @error And $aRet[0] = 0 Then
        $aRet = DllCall("Ws2_32.dll", "str", "inet_ntoa", "int", DllStructGetData($sockaddr, 3))
        If Not @error Then $aRet = $aRet[0]
    Else
        $aRet = 0
    EndIf

    $sockaddr = 0

    Return $aRet
EndFunc  ;==>SocketToIP


amel27 30-05-2009 11:00 1130818

Цитата:

Цитата morgan1991
Но так и не понял как же всётаки работают все сервера игр, icq, и т.п. ?
В моём примере оба компьютера должны видеть IP адреса друг друга, если этого не происходит, то связь обрывается, т.к. двухсторонняя связь будет физически невозможна. »

адреса серверов известны (например, через DNS), а адрес подключившегося клиента серверу определить не проблема, пример UDF есть в справке и я его приводил: SocketToIP()

Belfigor 14-06-2009 18:05 1143054

Такой вопрос. Запускаю и клиент и сервер на одном компьютере, все работает ок.
Запускаю сервер на своем компьютере а клиент на другом. Клиент на другом компьютере моментально пишет что время ожидания ответа от сервера истекло, сервер же спустя секунд 10-20 отображает сообщение о том что "Связь с новым ID потеряна!".

Чем вызваны эти симптомы?

Вопрос отпал, достаточно быстро сделал клиент серверную часть работающую как чат.

SunnySan 30-06-2009 19:32 1155733

Вложений: 2
Прочитав немного эту ветку, решил попробовать написать свой чат клиент-сервер. Написал на основе примеров из справки. Сервер один и с него нельзя ни чего писать. Клиентов много (т.е. max 100).

lokky06 16-12-2009 18:04 1296952

Есть вопросик как реализовать простенький "СНИФЕР" IP И порт известны требуется получать данные как от клиента так и от сервера отправка только на сервер.


Время: 21:15.

Время: 21:15.
© OSzone.net 2001-