Client/server
Blitz3D Forums/Blitz3D Beginners Area/Client/server
| ||
Hello, I remember someone had tried successfully to make a client/server architecture (using TCP/IP) with Blitz (as client) and PureBasic as server. I wrote a very initial implementation, but I got some problems I can't resolve. If I run the two programs on ONE computer, it works. Between two computers, the connection is estabilished, but it seems the client sends TWO data packets, instead of one. Here it is the two sources. I hope you don't mind if one is written in PureBasic. Const MB_OK= 0 Const MB_ICONERROR= 16 ; --- TIPI DI MESSAGGIO Const MSG_NEW= 170 Const MSG_LIST= 240 Const MSG_LOGIN= 255 Const MSG_EVENT= 85 Const MSG_END= 226 ; --- TIPI DI EVENTO Const START= 24 Const ACCEPT= 129 Const MOVE= 204 Const ANSWER= 51 Const CHAT= 231 Const GAMEOVER= 7 ; --- CLASSE PLAYER Type Player Field Name$ Field IP% Field Enemy_IP% Field FlagFirst ; 1= ha richiesto la partita per primo Field TotalWon Field TotalLost End Type BUFFER_connessione=CreateBank(1024) Dim Utenti$(255) Port=6832 Server_IP$="192.168.1.3" Nome_Utente$=Input("User Name: ") ; si connette al server HANDLE_tcp=OpenTCPStream(Server_IP$,Port) If Not HANDLE_tcp MessageBox(0,"Impossibile stabilire una connessione con il server TW.","TWClient",MB_OK Or MB_ICONERROR) End EndIf DebugLog "Connesso." ; attende l'arrivo del pacchetto MSG_NEW ReadBytes(BUFFER_connessione,HANDLE_tcp,0,6) DebugLog PeekByte(BUFFER_connessione,0) DebugLog PeekInt(BUFFER_connessione,1) DebugLog PeekByte(BUFFER_connessione,5) Print PeekByte(BUFFER_connessione,0) Print PeekInt(BUFFER_connessione,1) Print PeekByte(BUFFER_connessione,5) c=PeekInt(BUFFER_connessione,1) ; attende l'arrivo del pacchetto MSG_LIST If c>1 ReadBytes(BUFFER_connessione,HANDLE_tcp,0,c) l=0 For i=1 To c t=PeekByte(BUFFER_connessione,i) If t=35 l=l+1 Else Utenti$(l)=Utenti$(l)+Chr$(t) EndIf DebugLog PeekByte(BUFFER_connessione,i) Next Print Utenti$(0) Print Utenti$(1) Print Utenti$(2) Print Utenti$(3) Print Utenti$(4) Print Utenti$(5) Print Utenti$(6) Print Utenti$(7) Print Utenti$(8) Print Utenti$(9) Print Utenti$(10) Print Utenti$(11) EndIf ; invia il pacchetto MSG_LOGIN DebugLog "MSG_LOGIN ..." ;tmp$=Chr(MSG_LOGIN)+Nome_Utente$+Chr(MSG_END) ;WriteString(HANDLE_tcp,tmp$) WriteString(HANDLE_tcp,Chr(MSG_LOGIN)+Nome_Utente$+Chr(MSG_END)) Print "Batti INVIO per uscire." e$=Input() CloseTCPStream(HANDLE_tcp) End ; --- TIPI DI MESSAGGIO #MSG_HELLO= 170 #MSG_LIST= 240 #MSG_LOGIN= -1 #MSG_EVENT= 85 #MSG_END= -30 ; --- TIPI DI EVENTO #START= 24 #ACCEPT= 129 #MOVE= 204 #ANSWER= 51 #CHAT= 231 #GAMEOVER= 7 ; --- CLASSE PLAYER Structure Player Name.s ID.l IP.l Enemy_ID.l Enemy_IP.l FlagFirst.b ; 1= ha richiesto la partita per primo TotalWon.l TotalLost.l EndStructure OpenConsole() InitNetwork() ExamineIPAddresses() res=NextIPAddress() Server_IP.s=IPString(res) tmp$=UCase(ProgramParameter()) If tmp$="/P" Or tmp$="/PORT" tmp$=ProgramParameter() Port=Val(tmp$) Else ; Port=6933 Port=6832 EndIf If CreateNetworkServer(0,Port) NewList PlayerList.Player() *BUFFER_connessioni=AllocateMemory(1024) OpenWindow(0,0,0,320,240,"Total War Server "+Str(Port),#PB_Window_SystemMenu|#PB_Window_ScreenCentered) Repeat WEvent=WindowEvent() If WEvent=#PB_Event_CloseWindow Quit=1 EndIf SERVER_event=NetworkServerEvent() If SERVER_event Debug "evento server" ID_client.l=EventClient() Select SERVER_event Case 1 Debug "nuova connessione di un client " ; ricava la lista dei giocatori connessi tmp$="" ResetList(PlayerList()) While NextElement(PlayerList()) tmp$+PlayerList()\Name+"#" Wend c=Len(tmp$)+1 ; invio del pacchetto MSG_HELLO Debug "MSG_HELLO" PokeB(*BUFFER_connessioni,#MSG_HELLO) PokeL(*BUFFER_connessioni+1,c) PokeB(*BUFFER_connessioni+5,#MSG_END) SendNetworkData(ID_client,*BUFFER_connessioni,6) If c>1 ; invio del pacchetto MSG_LIST Debug "MSG_LIST" PokeB(*BUFFER_connessioni,#MSG_LIST) PokeS(*BUFFER_connessioni+1,tmp$) PokeB(*BUFFER_connessioni+c,#MSG_END) SendNetworkData(ID_client,*BUFFER_connessioni,c) EndIf Case 4 Debug "chiusa una connessione" Default Debug "arrivati dati" PrintN("arrivati dati") RequestLength.l=ReceiveNetworkData(ID_client,*BUFFER_connessioni,512) Debug "LENGTH= "+Str(RequestLength) PrintN("LENGTH= "+Str(RequestLength)) For a=0 To RequestLength-1 Debug PeekB(*BUFFER_connessioni+a) PrintN(Str(PeekB(*BUFFER_connessioni+a))) Next Select PeekB(*BUFFER_connessioni+4) Case #MSG_LOGIN Debug "MSG_LOGIN" PrintN("MSG_LOGIN") c=PeekL(*BUFFER_connessioni)-2 tmp$=PeekS(*BUFFER_connessioni+5,c) Debug tmp$ PrintN(tmp$) Debug ID_client PrintN(Str(ID_client)) IP=GetClientIP(ID_client) Debug IPString(IP) PrintN(IPString(IP)) ; aggiunge un nuovo giocatore alla lista AddElement(PlayerList()) PlayerList()\Name=tmp$ PlayerList()\ID=ID_client PlayerList()\IP=IP Case #MSG_EVENT Debug "MSG_EVENT" EndSelect ; Gosub ProcessRequest EndSelect Else Sleep_(20) EndIf Until Quit=1 CloseNetworkServer(0) Else MessageBox_(0,"Non è possibile creare il server.","TWServer",#MB_OK|#MB_ICONERROR) EndIf End Basically it works like this: when the server gets a new connection from a client, it sends a MSG_HELLO packet that contains the LENGTH (as LONG) of the further MSG_LIST to be sent, that is a list of all connected user names. In this way the Blitz client waits for the right size of the MSG_LIST packet. Then the client sends a MSG_LOGIN packet with a new user name to be added. As said, it works when both server and client are on the same computer. I tried on two different computers of my home network, but it doesn't work properly. It seems the server receives two MSG_LOGIN packets. Here it is a sample of the output of the PB server program : data arrived LENGTH=4 7 0 0 0 data arrived LENGTH=7 -1 65 66 67 68 69 -30 The bytes are correct, but I don't understand why it gets two packets. When you do: WriteString(HANDLE_tcp,Chr(MSG_LOGIN)+Nome_Utente$+Chr(MSG_END)) Each Blitz string is stored in the file as a 4 byte integer followed by the characters that form the string. Actually if you look above, 7 is the length of the string. But I can't understand why I get two packets. If I try in local (127.0.0.1), I only get one packet like this: data arrived LENGTH=11 7 0 0 0 -1 65 66 67 68 69 -30 May you give me some suggestions ? Thank you VERY MUCH in advance. |
| ||
suggestion: have you tried using writeline instead of writestring? |
| ||
Thanks for reply. Actually I tried with WriteBytes() and it gets all bytes in ONE packet. I'll try WriteLine() too just for curiosity. WriteString() is useful because it adds the length and it's handy (I could it manually though). I could even live with two packets, but I should be sure it always sends two packets... in local it sends only one packet. |