Here's an example. I took Mike Delling's chat client code, and simply modified it to retry if it can't connect. When it can't connect (Which happens if you don't run the server, and have the client point to the server), the "can't connect" text doesn't show up, and it's difficult or impossible to move the window around. However, if you let it run this way for a while, and then start up the server, all the "can't connect" messages will show up, and everything will be fine.
Code: Select all
; Chat Server X-Ample by Mike Delling
;
; With complete documentation for correctly networking in PB. :o)
If InitNetwork()=0
MessageRequester("","Could not initialize WSA.",0)
End
EndIf
hWin=OpenWindow(0,0,0,600,200,#PB_Window_ScreenCentered|#PB_Window_SystemMenu,"PB Chat Client")
If hWin=0
MessageRequester("","Could not open window.",0)
End
EndIf
If CreateGadgetList(hWin)=0
MessageRequester("","Could not Create Gadgetlist.",0)
EndIf
; -----------------------------------------
: Dimenstions & Structures & Constants
; -----------------------------------------
#NetworkEvent = #WM_User +1 ; For incomeing events from server
#MaxCommands = 10
#Maxlines = 1024
Dim commands$(#MaxCommands)
*receivebuffer=GlobalAlloc_(#GMEM_FIXED | #GMEM_ZEROINIT, 12000)
; -----------------------------------------
; Some Procedures
; -----------------------------------------
Procedure.w MyGetCommand(a$)
For a = 0 To #MaxCommands : commands$(a) = "" : Next
len = Len(a$) : ak = 1
;
Repeat
letter$ = Mid(a$,ak,2)
If letter$ <> "@!"
letter$ = Mid(a$,ak,1)
commands$(akcommand)+letter$ : ak + 1
EndIf
;
If letter$ = "@!"
akcommand + 1 : ak + 2
EndIf
Until ak >= len
;
ProcedureReturn akcommand
EndProcedure
;-----------------------------------
; PROC - Send Datas through network
;-----------------------------------
Procedure MySend(id,txt$)
; calculate bufferlength
length.l=Len(txt$)+1 ; String + EOL
length.l+4 ; Packet length at beginning
length.l+4 ; CRC32
*mem.l=GlobalAlloc_(#GMEM_FIXED | #GMEM_ZEROINIT, length.l)
PokeL(*mem.l,length.l) ; Store the Header (Size of Packet)
PokeS(*mem.l+4,txt$) ; Store String (Datas)
crc.l=CRC32Fingerprint(*mem.l+4,length.l-8) ; Create CRC32 Checksum
PokeL(*mem.l+length.l-4,crc.l) ; Store it at the end of the packet
Repeat ; Loop for Datasend
send=send_(id,*mem.l,length,0) ; Send our Datas
sended+send ; Count our sended Bytes
If send=#SOCKET_ERROR
wsaerror=WSAGetLastError_()
If wsaerror=#WSANOTINITIALISED:err$="Wsa not initialized":EndIf
If wsaerror=#WSAENETDOWN :err$="The Windows Sockets implementation has detected that the network subsystem has failed.":EndIf
If wsaerror=#WSAENOTCONN :err$="Socket not connected.":EndIf
If wsaerror=#WSAEINTR :err$="The (blocking) call was canceled using WSACancelBlocking":EndIf
If wsaerror=#WSAEINPROGRESS :err$="A blocking Windows Sockets operation is in progress.":EndIf
If wsaerror=#WSAENOTSOCK :err$="The descriptor is not a socket.":EndIf
If wsaerror=#WSAEOPNOTSUPP :err$="MSG_OOB was specified, but the socket is not of type SOCK_STREAM.":EndIf
If wsaerror=#WSAESHUTDOWN :err$="The socket has been shut down; it is not possible to recv on a socket after shutdown has been invoked with how set to 0 or 2.":EndIf
If wsaerror=#WSAEMSGSIZE :err$="The datagram was too large to fit into the specified buffer and was truncated.":EndIf
If wsaerror=#WSAEINVAL :err$="The socket has not been bound with bind.":EndIf
If wsaerror=#WSAECONNABORTED :err$="The virtual circuit was aborted due to timeout or other failure.":EndIf
If wsaerror=#WSAECONNRESET :err$="The virtual circuit was reset by the remote side.":EndIf
If wsaerror=#WSAEWOULDBLOCK :err$="The socket is marked as nonblocking":EndIf
If wsaerror=#WSAEWOULDBLOCK:send=0:sended=0:Delay(250):EndIf
EndIf ; Errorcheck
Until sended>=length Or send=#SOCKET_ERROR ; Loop as long as all Datas has been send
GlobalFree_(*mem) ; Free our Memory again
ProcedureReturn send
EndProcedure
#HostIPText = 1
#HostString = 2
#NickText = 3
#NickString = 4
#Connect = 5
#ChatWindow = 6
#ChatText = 7
#Send = 8
#ReturnKey = 1
TextGadget (#HostIPText,10,13,50,20,"Host/IP:")
StringGadget (#HostString,70,10,150,20,"127.0.0.1")
TextGadget (#NickText,230,13,50,20,"Nickname:")
StringGadget (#NickString,290,10,150,20,"Eliot")
ButtonGadget (#Connect,450,10,100,20,"Connect")
ListIconGadget(#ChatWindow,10,40,580,120,"",500)
StringGadget (#ChatText,10,170,500,20,"")
ButtonGadget (#Send,520,170,70,20,"Send"):AddKeyboardShortcut(0,#PB_Shortcut_Return,#ReturnKey)
Procedure showmsg(msg$)
Shared lines,maxlines
AddGadgetItem(#ChatWindow,lines,msg$)
SendMessage_(GadgetID(#ChatWindow),#LVM_ENSUREVISIBLE,lines,1)
lines+1
EndProcedure
Procedure window(WindowID, Message, wParam, lParam)
Shared hSocket,*receivebuffer.l,totalreceived.l,receiveexpected.l,received
Result = #PB_ProcessPureBasicEvents
; Handle Networkevents here
If Message=#NetworkEvent
serverevent=NetworkClientEvent(hSocket) ; What happens?
If serverevent=2 ; Rawdata received (2 is described by the PB Manual)
If receiveexpected>0
received=recv_(hSocket,*receivebuffer.l+totalreceived.l,receiveexpected-totalreceived,0)
If received<>#SOCKET_ERROR
If received>0:totalreceived+received:EndIf
If totalreceived=PeekL(*receivebuffer.l) ; Is our packet complete?
command$=PeekS(*receivebuffer+4) ; Get our Command-String from Memorybuffer
anz=MyGetCommand(command$) ; Tokanize our Command-String
totalreceived=0 ; Datapacket complete, reset value and wait for new one
receiveexpected=-1 ; Wait for new packetheader but do not execute the next part!
; Message Processing here
If commands$(0)="STRG"
;AddGadgetItem(#ChatWindow,-1,commands$(1)+" > "+commands$(2))
showmsg(commands$(1)+" > "+commands$(2))
EndIf
If commands$(0)="ENTR"
;AddGadgetItem(#ChatWindow,-1,commands$(1)+" entered the chat.")
showmsg(commands$(1)+" entered the chat.")
EndIf
EndIf
EndIf
EndIf
If totalreceived<3 And receiveexpected=0 ; Receive our Packetheader till it is complete
received=recv_(hSocket,*receivebuffer+totalreceived,4-totalreceived,0) ; Receive TCP/IP Buffer (max. 4 Bytes)
If received<>#SOCKET_ERROR
If received=4
receiveexpected=PeekL(*receivebuffer)
EndIf ; Completed yet?
If received>0:totalreceived+received:EndIf ; Count our Received bytes (we need 4!)
commands$(0)="" ; Erase our String to avoid multihandling
EndIf
EndIf
If receiveexpected=-1:receiveexpected=0:EndIf ; Ready to receive next dataheader again!!
EndIf ; End RAW Data receive
EndIf
ProcedureReturn Result
EndProcedure
SetWindowCallback(@window())
Repeat
winevent.l=WaitWindowEvent() ; Get Window-Event ID
wineventgadget.l=EventGadgetID() ; Get Gadget-Event ID
wineventtype=EventType() ; Get Windows Event Type
winid=EventWindowID() ; Get window where the event occurs
winmenu=EventMenuID() ; Get MenuID
lastgadget.l=wineventgadget.l
; Handle Windowevents here
If winevent.l=#PB_Event_Menu ; Menuchecking for keyboard shortcuts
If winmenu=#Returnkey
If LCase(GetGadgetText(#Chattext))="send"
nick$=InputRequester("Send File to user...","Please type in the nickname of user:","")
file$=OpenFileRequester("Select file to send to "+nick$,"","*.*","")
mysend(hSocket,"FILE@!"+nick$+"@!"+file$+"@!"+StrU(FileSize(file$),#Long)+"@!")
EndIf
If mysend(hSocket,"STRG@!"+GetGadgetText(#NickString)+"@!"+GetGadgetText(#Chattext)+"@!")=#SOCKET_ERROR
showmsg("Could not send String.")
; AddGadgetItem(#ChatWindow,-1,"Could not send String.")
Else
;AddGadgetItem(#ChatWindow,-1,GetGadgetText(#NickString)+" > "+GetGadgetText(#Chattext))
showmsg(GetGadgetText(#NickString)+" > "+GetGadgetText(#Chattext))
SetGadgetText(#ChatText,"")
EndIf
EndIf
EndIf
If winevent.l=#PB_Event_Gadget ; Any Gadgetevent here?
If wineventgadget=#Connect ; User try to connect
; -------------------------------------
; -------------------------------------
; -------------------------------------
connt:
hSocket=OpenNetworkConnection(GetGadgetText(#HostString),6000)
If hSocket=0
showmsg("we didn't connect")
Delay(10)
; MessageRequester("","Could not connect to server.",0)
Else
; Connection successfull, add a Usermessage to the Window
WSAAsyncSelect_(hSocket,hWin,#NetworkEvent,#FD_READ | #FD_Write |#FD_OOB)
mysend(hSocket,"ENTR@!"+GetGadgetText(#NickString)+"@!")
;AddGadgetItem(#ChatWindow,-1,"Connected to server.")
showmsg("Connected to server.")
; We are now successfully connected
EndIf
If hSocket=0 : Goto connt : EndIf
; ---------------------------------------
; ---------------------------------------
; ---------------------------------------
EndIf ; End Connect
If wineventgadget=#Send
If mysend(hSocket,"STRG@!"+GetGadgetText(#NickString)+"@!"+GetGadgetText(#Chattext)+"@!")=#SOCKET_ERROR
AddGadgetItem(#ChatWindow,-1,"Could not send String.")
Else
;AddGadgetItem(#ChatWindow,-1,GetGadgetText(#NickString)+" > "+GetGadgetText(#Chattext))
showmsg(GetGadgetText(#NickString)+" > "+GetGadgetText(#Chattext))
SetGadgetText(#ChatText,"")
EndIf
EndIf
EndIf ; End gadgetevents condition
Until winevent=#PB_Event_CloseWindow
End