forum.boolean.name

forum.boolean.name (http://forum.boolean.name/index.php)
-   BlitzMax (http://forum.boolean.name/forumdisplay.php?f=104)
-   -   Вопрос-Ответ (для новичков BlitzMax) (http://forum.boolean.name/showthread.php?t=13756)

Jlemyp 19.11.2014 00:09

Ответ: Вопрос-Ответ (для новичков BlitzMax)
 
Спасибо за совет.Действительно, глаза хотят а руки боятся.Просто я думал, что можно простой сервер написать в строк 7,но видел здесь примерчик что он как то в Типах и все такое.Нет описания на русском операторов связаных с сетью,что бы понять что за что отвечает.Если бы было,мне бы стало проще.Хелп на английском,может у меня и версия BlitzMax-а низкая ( 1.45 ) Начну стараться и грызть науку.

Randomize 19.11.2014 00:58

Ответ: Вопрос-Ответ (для новичков BlitzMax)
 
Цитата:

Сообщение от Jlemyp (Сообщение 289503)
...

Смотри стандартный пример:
BlitzMax\samples\mak\gnetchat.bmx
И в этой же папке:
BlitzMax\samples\mak\gnetdemo.bmx
Второй особенно интересен. Код немного сложноват, но для экспериментов пойдёт.
В примерах используется стандартная библиотека gnet, она не очень производительна, но для простеньких игр и экспериментов подходит замечательно.

Arton 19.11.2014 02:11

Ответ: Вопрос-Ответ (для новичков BlitzMax)
 
Цитата:

Сообщение от Jlemyp (Сообщение 289503)
Нет описания на русском операторов связаных с сетью,что бы понять что за что отвечает.

Справочник по BlitzMax

Jlemyp 20.11.2014 23:50

Ответ: Вопрос-Ответ (для новичков BlitzMax)
 
Мне стыдно,но я полный нуль в этом.Почему не подключается клиент к серверу
сервер:
Strict
Import BRL.GNet
Global port=50000
Global host:TGNetHost=CreateGNetHost:TGNetHost()
GNetListen( host,port )

While Not KeyHit( KEY_ESCAPE )

Wend

клиент:
Import BRL.GNet
Global port=50000
SeedRnd MilliSecs()
Global host:TGNetHost=CreateGNetHost:TGNetHost()
f=GNetConnect(host,"127.0.0.1",port)
Print f

подскажите направление моей тупости.

Jlemyp 21.11.2014 12:12

Ответ: Вопрос-Ответ (для новичков BlitzMax)
 
пожалуйста,напишите в 5 строчках создание серва и создание клиента.Как узнать полключился клиент к серву или нет?

Randomize 21.11.2014 12:25

Ответ: Вопрос-Ответ (для новичков BlitzMax)
 
GNetSync(host) в цикле сервера.
Эта ф-ция - обработчик сервера. Если её не вызывать он и работать не будет.
Не забывай после работы закрывать соединения!
Иначе можно получить кучу багов из-за открытых остаточных соединений (см. порт занят).

Jlemyp 21.11.2014 14:46

Ответ: Вопрос-Ответ (для новичков BlitzMax)
 
Огромное спасибо!!! С GNetSync(host) клиент сразу подключился.Я немного буду задавать глупые для Вас вопросы,но хотел бы получать взамен полезные ответы для себя.

Randomize 21.11.2014 16:53

Ответ: Вопрос-Ответ (для новичков BlitzMax)
 
Цитата:

Сообщение от Jlemyp (Сообщение 289578)
Я немного буду задавать глупые для Вас вопросы,но хотел бы получать взамен полезные ответы для себя.

Без проблем. Обращайся. Мы тут для того и сидим.

Jlemyp 21.11.2014 21:52

Ответ: Вопрос-Ответ (для новичков BlitzMax)
 
Подключится,подключился,но передать данные зи клиента на сервер неполучается.Подскажите какую команду еще забыл..
сервер:
Import BRL.GNet
Global port=50000
SeedRnd MilliSecs()
Global host:TGNetHost=CreateGNetHost:TGNetHost()
Global me:TGNetObject=CreateGNetObject:TGNetObject(host)
GNetListen( host,port )

While Not KeyHit( KEY_ESCAPE )
GNetSync(host)
If Not me Print GetGNetString$(me,0)
Wend

CloseGNetHost (host)

клиент :
Import BRL.GNet
Global port=50000
Global add$="127.0.0.1"
Global host:TGNetHost=CreateGNetHost:TGNetHost()
Global me:TGNetObject=CreateGNetObject:TGNetObject( host )

If GNetConnect(host,add,port)
SetGNetString (me,0,"Ready")
EndIf

CloseGNetHost (host)

Randomize 22.11.2014 11:02

Ответ: Вопрос-Ответ (для новичков BlitzMax)
 
Cообщения, что на сервере, что на клиенте обрабатываем так:
Код:

For Local obj:TGNetObject=EachIn GNetObjects( host )
        If obj.State()=GNET_CLOSED Continue ' Закрытые сообщения не нужны
        Print GetGNetString( obj, 0)
Next

Рекомендую ещё раз изучить примеры из стандартной поставки BlitzMax.
Цитата:

Сообщение от Randomize (Сообщение 289506)
Смотри стандартный пример:
BlitzMax\samples\mak\gnetdemo.bmx


Jlemyp 22.11.2014 15:07

Ответ: Вопрос-Ответ (для новичков BlitzMax)
 
как правильно понять эту ошибку - Unhandled Exception: Assert failed
необработанное исключение ? Это вылетает когда обрабатываю сообщения на сервере.

Jlemyp 22.11.2014 23:19

Ответ: Вопрос-Ответ (для новичков BlitzMax)
 
провел 5 часов не вставая из-за компа,выпил 3 бокала чая,но так и не смог передать от клиента серверу данные.Пробывал понять как устроен на сокетах сервер и тоже упирался в тупик.Не хочу на Blitz3d там 2d графика плохо реализованна, а Fastimage с ключем нет.Хочу понять здесь сеть,но нервы начинают сдавать.

Жека 27.11.2014 09:00

Ответ: Вопрос-Ответ (для новичков BlitzMax)
 
Вложений: 2
Я когда-то делал простенький клиент-сервер на максе, на основе TCP.

Суть:
1. клиенты представляют из себя движущиеся объекты (в пределах экрана)
2. сервер должен следить за перемещениями этих объектов, отображая всех на экране

Данные от клиентов передаются 1 раз в секунду, можно изменить "timeSendPosInterval = 1000".

Клиенты могут отправлять текстовую инфу серверу, она отобразится в поле "info".

Подключение происходит на локальный адрес, можно изменить: "remoteIp = HostIp("127.0.0.1")".

По умолчанию порт для подключения 50000, при наличии файла port.txt в корне с exe-шниками - порт загружается оттуда.

Примечание: для получения русских символов есть простецкий конвертер в файле utils.bmx.

Запуск:
1. запустить tcpServer
2. запустить tcpClient один или несколько раз

tcpClient.bmx
Код:

SuperStrict

Include "utils.bmx"

AppTitle = "tcpServer"



Global maxLines:Int = 20

Global strTmp:String = ""

Global info:String


Graphics 800, 600

SetImageFont(LoadImageFont("arial.ttf", 12))

Local port:Int = 50000
If(FileType("port.txt") = 1)
        port = Int(LoadText("port.txt"))
EndIf

Global server:TServer = New TServer
server.start(port)

Local char:Short


While Not(KeyHit(KEY_ESCAPE) Or AppTerminate())

        server.update()
       
        char = GetChar()
        If(char <> 0) Then server.sendToAll(Chr(char))
       
        DrawText("Port: " + port + ", online: " + server.onlineCount, 20, 50)
        DrawText("Info: " + info, 20, 70)
       
        server.drawPos()
       
        Flip()
        Cls()
       
Wend

server.stop()

End


Function socketSend(sock:TSocket, text:String)
       
        text:+"~r~n"
        sock.Send(text, Len(text))
        DebugLog("send: " + text)
       
End Function


Function socketRecv:String(sock:TSocket, bufData:Byte[], bufSize:Int)
       
        If(sock.ReadAvail() = 0) Then Return Null
       
        strTmp = ""
        Local size:Int = 0
       
        While(sock.ReadAvail() > 0)
                flushBuf(bufData, bufSize)
                size = sock.ReadAvail()
                If(size > bufSize) size = bufSize
                sock.Recv(bufData, size)
                strTmp:+String.FromCString(bufData).Trim()
        Wend
       
        strTmp = convertFromAnsi(strTmp)
               
        Return strTmp
       
End Function



Type TServer
        Field socket:TSocket
        Field connect:TSocket

        Const bufSize:Int = 255
        Field bufData:Byte[] = New Byte[bufSize]
        Field bufStr:String[] = Null

        Field listMsg:TList = New TList

        Field listClients:TList = New TList
       
        Field cmd:String
       
        Field onlineCount:Int
       
       
       
        'запуск
        Method start(port:Int = 5000)
                socket = CreateTCPSocket()
                BindSocket(socket, port)
                SocketListen(socket)
        End Method

       
        'остановка
        Method stop()
                CloseSocket(socket)
        End Method


        'добавление нового клиента в список
        Method clientAdd:TClient(socket:TSocket)
                Local cli:TClient = New TClient
                cli.socket = socket
                listClients.addLast(cli)
                onlineCount:+1
                Return cli
        End Method
       
       
        'удаление клиента из списка
        Method clientRemove(client:TClient)
                listClients.Remove(client)
                onlineCount:-1
                DebugLog("disconnect " + client.getId() + " at " + CurrentTime())
        End Method
       
       
        'обработка клиентов
        Method update()
       
                'подключение новых клиентов
                If(connect = Null)
                        connect = SocketAccept(socket)
                        If(connect <> Null)
                                clientAdd(connect)
                                socketSend(connect, "ID")
                                connect = Null
                        EndIf
                EndIf
               
       
                'прослушивание клиентских сокетов
                If(listClients.IsEmpty()) Return
               
                Local params:String[]
               
                For Local cli:TClient = EachIn listClients
                       
                        'клиент отключился
                        If(cli.socket.Connected() = False)
                                clientRemove(cli)
                                Continue
                        EndIf
                       
                        'получение и обработка данных
                        strTmp = socketRecv(cli.socket, bufData, bufSize)
                        If(strTmp <> "")
                                bufStr = strTmp.Split("~r~n")
                                For Local k:Int = 0 Until bufStr.Length
                                        cmd = bufStr[k].Trim()
                                        If(cmd = "") Continue
                                        'разделение на параметры
                                        params = commandParseCommand(cli, cmd)
                                        'выполнение
                                        commandProcessCommand(cli, params)
                                        'добавление в чат
                                        strTmp = cli.getId() + ": " + cmd
                                        listMsg.AddLast(strTmp)
                                        If(listMsg.Count() > maxLines) Then listMsg.Remove(listMsg.First())
                                        DebugLog(strTmp)
                                Next
                        EndIf
                Next
       
        End Method
       
       
        'разбор команды
        Method commandParseCommand:String[] (client:TClient, cmd:String)
                Local mas:String[] = cmd.Split(" ")
                Return mas
        End Method
       
       
        'выполнение команд
        Method commandProcessCommand(client:TClient, params:String[])
                Local cmd:String = params[0]
                If(cmd = "ID")
                        client.setId(Int(params[1]))
                Else If(cmd = "POS")
                        client.setPos(Int(params[1]), Int(params[2]))
                Else
                        info = cmd
                EndIf
        End Method
       
       
        'массовая рассылка всем, кроме указанного
        Method sendToOther(client:TClient, text:String)
                If(listClients.IsEmpty()) Then Return
       
                For Local cli:TClient = EachIn listClients
                        If(cli <> client)
                                socketSend(cli.socket, text)
                        EndIf
                Next
               
        End Method
       
        'массовая рассылка всем, кроме указанного
        Method sendToAll(text:String)
                sendToOther(Null, text)
        End Method
       
        'рисование позиций на карте
        Method drawPos()
                If(listClients.IsEmpty()) Then Return
                Local px:Int, py:Int, sz:Int = 20
                Local name:String
               
                For Local cli:TClient = EachIn listClients
                        px = cli.getX()
                        py = cli.getY()
                       
                        cli.adjustColor()
                        DrawRect(px, py, sz, sz)
                       
                        SetColor(200, 200, 200)
                        name = "" + cli.getId()
                        DrawText(name, px - (TextWidth(name) - sz) * 0.5, py - 17)
                Next
               
        End Method
       
End Type


Type TClient
        Field socket:TSocket
        Field obj:TObj = New TObj
       
        Field red:Int, green:Int, blue:Int
       
       
        Method setId(id:Int)
                obj.id = id
                red = Rand(100, 255)
                green = Rand(100, 255)
                blue = Rand(100, 255)
        End Method
       
        Method adjustColor()
                SetColor(red, green, blue)
        End Method
       
        Method getId:Int()
                Return obj.id
        End Method
       
        Method setPos(x:Int, y:Int)
                obj.x = x
                obj.y = y
        End Method
       
        Method getX:Int()
                Return obj.x
        End Method
       
        Method getY:Int()
                Return obj.y
        End Method
       
End Type


Type TObj
        Field name:String
        Field id:Int
        Field x:Int, y:Int
End Type



tcpClient.bmx
Код:

SuperStrict

SeedRnd(MilliSecs())

AppTitle = "tcpClient"

Include "utils.bmx"

Local remotePort:Int = 50000
If(FileType("port.txt") = 1)
        remotePort = Int(LoadText("port.txt"))
EndIf
Local remoteIp:Int = HostIp("127.0.0.1")

Global cliSocket:TSocket = CreateTCPSocket()
ConnectSocket(cliSocket, remoteIp, remotePort)

Global bufSize:Int = 255
Global bufData:Byte[] = New Byte[bufSize]

Global bufStr:String[] = Null

Global listMsg:TList = New TList

Global maxLines:Int = 20

Global screenW:Int = 800
Global screenH:Int = 600

Graphics screenW, screenH
SetImageFont(LoadImageFont("arial.ttf", 16))
 
Global text:String
Global strTmp:String

text = ""

Global ch:Int = 0

Global onConnect:Int = True

Global posX:Float, posY:Float, spdX:Float, spdY:Float
Global timeMoveStart:Int, timeMoveInterval:Int = 100

posX = Rand(screenW)
posY = Rand(screenH)
spdX = Rnd(-1, 1)
spdY = Rnd(-1, 1)

Global timeSendPosStart:Int, timeSendPosInterval:Int = 1000


If(Not(SocketConnected(cliSocket)))
        DrawText "Server is not run. Try to connecting later.", 20, 20
        DrawText "Press any key to exit.", 40, 50
        WaitKey()
        End
EndIf

Local rez:Int = False

Global onRunning:Int = True


While(onRunning = True)
       
        If(KeyHit(KEY_ESCAPE) Or AppTerminate())
                onRunning = False
                Exit
        EndIf
       
       
        drawMessages()
               
        SetColor 155, 155, 155
        DrawLine 10, 10, screenW - 10, 10
        DrawLine 10, screenH - 50, screenW - 10, screenH - 50
        DrawLine 10, screenH - 10, screenW - 10, screenH - 10
       
        SetColor 255, 255, 255
        DrawText "> " + text, 10, screenH - 40
       
        If(MilliSecs() Mod 1000 < 500)
                DrawRect 10 + TextWidth("> " + text) + 2, screenH - 40, 2, 20
        EndIf
       
        DrawRect(posX, posY, 20, 20)
       
        Flip()
        Cls()
       
        rez = checkInput()
       
        If(rez = True) 'нажали Enter
                send(text)
                text = ""
        EndIf
       
        recv()
       
        If(Not(SocketConnected(cliSocket)))
                Exit
        EndIf
       
        moveObject()
       
        If(MilliSecs() - timeSendPosStart >= timeSendPosInterval)
                send("POS " + Int(posX) + " " + Int(posY))
                timeSendPosStart = MilliSecs()
        EndIf
       
Wend


CloseSocket(cliSocket)
 
End



Function moveObject()
        If(MilliSecs() - timeMoveStart < timeMoveInterval) Then Return
       
        posX:+spdX * 3
        posY:+spdY * 3
       
        If((posX <= 0 And spdX < 0) Or (posX >= screenW And spdX > 0))
                spdX:*- 1
        EndIf
        If((posY <= 0 And spdY < 0) Or (posY >= screenH And spdY > 0))
                spdY:*- 1
        EndIf
       
        If(Rand(100) < 5)
                spdX = Rnd(-1, 1)
                spdY = Rnd(-1, 1)
        EndIf
       
        timeMoveStart = MilliSecs()
End Function


Function drawMessages(x0:Int = 20, y0:Int = 20)
       
        If(listMsg.IsEmpty()) Then Return
       
        Local px:Int = x0, py:Int = y0
        For Local k:Int = 0 Until listMsg.count()
                px = x0
                strTmp = String(listMsg.ValueAtIndex(k))
                If(Mid(strTmp, 1, 2) = "я:")
                        SetColor 255, 255, 0
                ElseIf(Mid(strTmp, 1, 7) = "сервер:")
                        SetColor 255, 0, 0
                        'px:+5
                Else
                        SetColor 255, 255, 255
                EndIf
                DrawText strTmp, px, py
                py:+20
        Next

End Function


Function checkInput:Int()
        ch = GetChar()
        If(ch <> 0)
                text = text + Chr(ch)
                If(ch <> 32) text = text.Trim()
               
                If(ch = 8) 'backspace
                        If(Len(text) > 0)
                                text = Left(text, Len(text) - 1)
                        EndIf
                EndIf
        EndIf
       
        If(ch = 13)
                Return True
        Else
                Return False
        EndIf
End Function


Function send(msg:String)
               
        listMsg.AddLast("я: " + MSG)
        If(listMsg.Count() > maxLines) Then listMsg.Remove(listMsg.First())
        msg:+"~r~n"
        cliSocket.send(msg, Len(msg))
       
End Function


Function recv()
        If(cliSocket.ReadAvail() = 0) Then Return
       
        strTmp = ""
       
        While(cliSocket.ReadAvail() > 0)
                flushBuf(bufData, bufSize)
                cliSocket.Recv(bufData, bufSize)
                strTmp:+String.FromCString(bufData).Trim()
        Wend
       
        strTmp = convertFromAnsi(strTmp)
       
        bufStr = strTmp.Split(Chr(10))
        For Local k:Int = 0 Until bufStr.Length
                If(bufStr[k].Trim() = "") Then Continue
                listMsg.AddLast(bufStr[k].Trim())
                If(listMsg.Count() > maxLines) Then listMsg.Remove(listMsg.First())
        Next

        'разбор команды
        If(strTmp = "ID")
                text = "ID " + String(Rand(1000000))
                send(text)
        Else If(strTmp = "QUIT")
                onRunning = False
        EndIf
       
End Function



utils.bmx
Код:

Function flushBuf(buf:Byte Ptr, size:Int)
        For Local k:Int = 0 Until size
                buf[k] = 0
        Next
End Function


Function convertToAnsi:String(text:String)
        Local str:String = ""
        Local count:Int = Len(text)
        For Local k:Int = 0 Until count
                If(text[k] >= 1040 And text[k] <= 1103)
                        str:+Chr(text[k] - 1040 + 192)
                ElseIf(text[k] = 1025) 'Ё
                        str:+Chr(168)
                ElseIf(text[k] = 1105) 'ё
                        str:+Chr(184)
                Else
                        str:+Chr(text[k])
                EndIf
        Next
        Return str
End Function


Function convertFromAnsi:String(text:String)
        Local str:String = ""
        Local count:Int = Len(text)
        For Local k:Int = 0 Until count
                If(text[k] >= 192 And text[k] <= 255)
                        str:+Chr(text[k] - 192 + 1040)
                ElseIf(text[k] = 168) 'Ё
                        str:+Chr(1025)
                ElseIf(text[k] = 184) 'ё
                        str:+Chr(1105)
                Else
                        str:+Chr(text[k])
                EndIf
        Next
        Return str
End Function



Прилагаю код и скомпиленные файлы.

ПС: Возможно, стоит оформить этот пост в раздел "FAQ и уроки".

Jlemyp 27.11.2014 10:13

Ответ: Вопрос-Ответ (для новичков BlitzMax)
 
Твой урок у меня уже есть и я его разбирал.Но возникали проблемы,все равно сервер не получает значения.Вопрос: Сервер обязательно должен быть сделан на основе Типов? Мне главное понять работу сокетов.Другой вопрос,как запустить несколько клиентов на одной машине?При запуске 2 клиента пишет ошибка и не запускается.

Жека 27.11.2014 12:53

Ответ: Вопрос-Ответ (для новичков BlitzMax)
 
Клиент должен знать ip адрес сервера и порт. Ошибка в клиенте будет только если сервер не запущен.
Какая конкретно ошибка возникает?
Кинь весь код, посмотрю.


Часовой пояс GMT +4, время: 06:28.

vBulletin® Version 3.6.5.
Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
Перевод: zCarot