PDA

Показать полную графическую версию : [решено] Коннект


Страниц : 1 [2]

morgan1991
05-04-2009, 00:25
Скажите пожалуйста, а можно ли передавать файлы от клиента к серверу?

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

morgan1991
09-04-2009, 01:55
Т.е. нужно превратить файл в бинарные данные, а потом обратно? А можно поподробнее?

morgan1991
09-04-2009, 15:12
Сделал такой скриптик,

Клиент делает следующее:
$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
Сделал такой скриптик, »
Не прокатил такой скрипт, через него можно передавать файлы только размером не более 250 к/байт.
Помогите пожалуйста, каким образом всётаки можно передать файл от клиента к серверу?

amel27
10-04-2009, 13:42
каким образом всётаки можно передать файл от клиента к серверу? »Не так все просто - тут нужно подобрать оптимальный для себя протокол обмена - команды, данные, подтверждения и т.д. Вариантов куча - все зависит от задачи. Вот пример односторонней передачи данных (без подтверждения) - сначала имя файла, размер, потом данные, при ошибке сессия сбрасывается.

сервер:
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
Спасибо огромное, буду разбираться.

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

morgan1991
13-05-2009, 16:48
Додумался сам, вот что получилось:

Сервер:
#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
Я сделал сам двух стороннюю связь с неограниченным колличеством клиентов.
Но так и не понял как же всётаки работают все сервера игр, 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
Но так и не понял как же всётаки работают все сервера игр, icq, и т.п. ?
В моём примере оба компьютера должны видеть IP адреса друг друга, если этого не происходит, то связь обрывается, т.к. двухсторонняя связь будет физически невозможна. »адреса серверов известны (например, через DNS), а адрес подключившегося клиента серверу определить не проблема, пример UDF есть в справке и я его приводил: SocketToIP()

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

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

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

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

lokky06
16-12-2009, 18:04
Есть вопросик как реализовать простенький "СНИФЕР" IP И порт известны требуется получать данные как от клиента так и от сервера отправка только на сервер.




© OSzone.net 2001-2012