Что нового

[Сеть, интернет] Помогите написать файловый сервер (аналог FTP)

sss

Продвинутый
Сообщения
332
Репутация
96
Всем доброго времени суток! Мне бы хотелось написать свой файловый сервер (причины: часто гоняю файлы по сети, инет не безлимит, DC++ постоянно глючит, каждый раз поднимать и настраивать FTP - морока, а потом еще и скачать AutoIt'ом...). В TCP... фукциях разбираюсь на уровне "чайник" (читающий со словарем :smile: ). Я думаю, алгоритм примерно такой:
1) запуск сервера
2) конектимся клиентом
3) "приветственные" сообщения (проверка связи и т.п.)
4) посылка серверу сообщения вида "хочу_скачать--имя файла"
5) сервер обрабатывает, говорит клиенту "согласен"
6) сервер читает выбранный файл в бинарном режиме и посылает пучками по n символов клиенту, дожидаясь от того подтверждения приема пучка
7) файл скачан, проверяем md5(не обязательно), клиент отключается
8. сервер ждет нового подключения.

В принципе, я реализовал такой алгоритм(будет ниже). Пучки были по 1000 (999) символов. Пытался скачать файл test.mp3 и для отладки в нек. местах будет непонятный код, ну это ладно :smile: . У меня почему застревает процесс передачи где-то на 20-30 Кб. Дальше ощущение что AutoIt "висит" или код неверен. Помогите решить проблему! Заранее спасибо!
Коды:
Код:
TCPStartup()

; открываем сокет на прослушку
;==============================================
$ip='192.168.0.2' ; это ип сервера, т.е. компа на котором запустили
$port='3333'
$MainSocket = TCPListen($ip, $port)

; если ошибка
If $MainSocket = -1 Then
    MsgBox(16,@error,'Ошибка открытия сокета!')
    Exit
EndIf

$ConnectedSocket = -1

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

;~ MsgBox(0,'','')

while 1
    if $ConnectedSocket=-1 Then
        _wait_Connection()
    Else
        $recv = TCPRecv($ConnectedSocket, 50)
        If @error Then $ConnectedSocket=-1
        If $recv = '~~begin' and $ConnectedSocket<> -1 then
            TCPSend($ConnectedSocket,'~~confirming')
            ExitLoop
        EndIf
    EndIf
WEnd

While 1
    if $ConnectedSocket=-1 Then
        _wait_Connection()
    Else
        $recv = TCPRecv($ConnectedSocket, 50)
        If @error Then $ConnectedSocket=-1
        If StringInStr($recv,'~~download¬')>0 and $ConnectedSocket<> -1 then
            $split=StringSplit($recv,'¬')
            $filename='test.mp3'
            $fileopen=FileOpen ( @ScriptDir & '\' & $filename, 16 )
            $fileread=FileRead($fileopen)
            TCPSend($ConnectedSocket,'~~ready')
            ExitLoop
        EndIf
    EndIf
WEnd

While 1
    if $ConnectedSocket=-1 Then
        _wait_Connection()
    Else
        $to_send=StringLeft($fileread,999)
        $fileread=StringTrimLeft($fileread,999)
        TCPSend($ConnectedSocket,$to_send)
        While 1
            $recv = TCPRecv($ConnectedSocket, 50)
            if $recv='~~ok' then
                ExitLoop
            EndIf
            if $ConnectedSocket=-1 Then Exit
        WEnd
        If @error Then $ConnectedSocket=-1
        if StringLen($fileread)<999 Then
            TCPSend($ConnectedSocket,'~~end')
            Exit
        EndIf
    EndIf
WEnd

TCPShutdown()

func _wait_Connection()
Do
    $ConnectedSocket = TCPAccept($MainSocket)
    Sleep(1000)
Until $ConnectedSocket <> -1
EndFunc
Код:
TCPStartup()

; Для отслеживания коннекта
;==============================================
$ConnectedSocket = -1
$file_to_write=@ScriptDir & '\test2.mp3'
;Коннект
;=======================================================
$server_ip='192.168.0.2' ; ип сервера
$server_port='3333'
$ConnectedSocket = TCPConnect($server_ip, $server_port)
If @error Then
    MsgBox(4112, "Ошибка", "Сервер не найден! Код ошибки: " & @error)
    Exit
endif


$ret = TCPSend($ConnectedSocket, '~~begin')
If @ERROR then Exit

While 1
    if $ConnectedSocket=-1 then
        Exit
    Else
        $recv = TCPRecv($ConnectedSocket, 50)
        If @error Then $ConnectedSocket=-1
        If $recv = '~~confirming' and $ConnectedSocket<> -1 then
            ExitLoop
        EndIf
    EndIf
WEnd

$ret = TCPSend($ConnectedSocket, '~~download¬test.mp3')
If @ERROR then Exit

While 1
    if $ConnectedSocket=-1 then
        Exit
    Else
        $recv = TCPRecv($ConnectedSocket, 50)
        If @error Then $ConnectedSocket=-1
        If $recv = '~~ready' and $ConnectedSocket<> -1 then
            ExitLoop
        EndIf
    EndIf
WEnd
$fileopen=FileOpen ( $file_to_write, 2+16 )
$recv=''
while 1
    $old_recv=$recv
    $recv = TCPRecv($ConnectedSocket, 1000)
    If @error Then $ConnectedSocket=-1
    if $recv='~~end' Then
        Exit
    Else
        if not $recv=$old_recv Then
            FileWrite($fileopen,$recv)
            TCPSend($ConnectedSocket, '~~ok')
        EndIf
    EndIf
WEnd
Если что, не пинайте, искал здесь и на оф. форуме по запросам "передать файл, сервер, закачать файл" и другие (на оф. форуме, ясно, было по англ.)
 

zlo-kazan

Скриптер
Сообщения
374
Репутация
100
У меня зависает где-то между 3-50Кб...
Совсем не понятно на каком именно этапе виснет и какая часть программы серверная/клиентская.

Добавь ToolTip/ConsoleWrite/msgbox на каждый цикл или часть цикла (в обе программы) и будет на много понятнее в какой части кода косяк. :scratch:
 
Автор
sss

sss

Продвинутый
Сообщения
332
Репутация
96
Как вариант попробую, ну а если вдруг не виснет? :'( И, конечно, код не идеальный. Посоветуйте как это можно лучше осуществить. (сегодня времени экспериментировать нет, только завтра, попробую впихнуть на каждый этап логописАние :smile: )
 

zlo-kazan

Скриптер
Сообщения
374
Репутация
100
Накидал tooltip... итог:

Клиент отсылает "ok" и дальше пытается принимать.
Сервер не получает "ok" и ждет дальше...

P.S. Судя по тултипу проблема в том, что при передаче ok сервер не принимает данные... он % времени тратит на проверку условий If.
 
Автор
sss

sss

Продвинутый
Сообщения
332
Репутация
96
Да, точно... Может он тратит время не на if, а на прослушку? Я даже не знаю, как это теперь реализовать... Теперь и сам четко увидел эту лажу, спасибо, буду думать...
P.S: а может, использовать UDP? Но у мего вроде обратной связи нет... (я не нашел чтобы сокет можно было использовать и на прием и на передачу - открывать 2 сокета?)
OffTopic:
P.P.S: Новый рекорд размера сохраненного файла - 75,1 Кб! :smile:
 

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5,379
Репутация
2,724
Sky-WaLkeR сказал(а):
...каждый раз поднимать и настраивать FTP - морока.

Написать более-менее работоспособный файловый сервер - еще большая морока. Если не стоит цель научиться писать файловые сервера, то советую использовать какое-нибудь готовое решение.
 

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5,379
Репутация
2,724
Вот наипростейший Web-сервер. 700 КБ без установки и каких-либо настроек. Запустил и качай в любом браузере файлы. Или в AutoIt через InetGet().
 
Автор
sss

sss

Продвинутый
Сообщения
332
Репутация
96
Спасибо за совет. Да, наверное, вы правы. Я и раньше пользовался подобным сервером (DENWER), но он навороченный и с апачем. Обязательно посмотрю сервер по вашей ссылке, спасибо.
 

Garrett

Модератор
Локальный модератор
Сообщения
3,999
Репутация
967
Sky-WaLkeR вот ещё небольшие файловые сервера, не требующие инсталляции.
По HTTP протоколу hfs.exe
По FTP протоколу ftpserv.exe
 

beliy

Продвинутый
Сообщения
372
Репутация
72
Кстати на будущее не мешало бы нам разобраться с передачей файлов - думаю фича затребованая...
 
Верх