Code archives/Networking/[UPDATED 3/2/2003] UDP client / Server
This code has been declared by its author to be Public Domain code.
Download source code
| |||||
Below is a working example of UDP HOST/CLIENT. the idea below is designed for only 1 host and 1 client. It should give a fairly good understanding of what has to happen. I leave the code not a a function or lib, but as an example for the anyone to study. | |||||
Graphics 640,300,32,2 AppTitle "Udp functions" ;Protocol ;Msg Id ;1 = Connect [C -> S] ;2 = Accept [? -> ?] + username ;3 = Pong [? -> ?] ;4 = Error [? -> ?] ;5 = Notice [S -> C] ;Ping Byte ;0 = NoPing ;1 = Ping ;Welcome Msg Global UdpGameName$="TestName" ;Error Codes Dim Error$(5) Error$(1) = "Game already started" Error$(2) = "Server is busy try again soon! Error$(3) = "Ilegal protocol" Error$(4) = "Check that TCP and UDP are not blocked, or in use, on the specified port" Error$(5) = "No response from server" Global UdpServer=True Global UdpStream,TcpStream Global UdpServerName$="Mr host",UdpClientName$="Guest" Global Udp=False Global UdpBusy=False,UdpIp=0,UdpPort=0 Global UdpSaveIp=0,UdpSavePort=0 Global UdpPing=False,UdpPingStart=MilliSecs(),UdpPingResult=0 Global UdpTime=False,UdpTimeStart=MilliSecs(),UdpTimeOut=5000,UdpTimeRetry=1 Print "-----------------------" Print "Welcome to the udp test" Print "-----------------------" Print "" Print "Type a user name" GetName$=Input$("> ") Print ">" Print "Choose a mode :" Print " 0 = client" Print " 1 = server" GetMode=Input("> ") If GetMode=0 Then Print ">" Print "Type the local port you want to use" GetLocalPort=Input("> ") Print ">" Print "Type server address :" Print "( This can be xxx.xxx.xxx.xxx or www.address.com )" GetAd$=Input$("> ") Print ">" Print "Type server port :" GetPort=Input("> ") GetResult=JoinGame(GetName$,GetAd$,GetLocalPort,GetPort) If GetResult > 0 Then Print Error$(GetResult) Goto EndOfApp End If Else Print ">" Print "Type a name for the server" GetGameName$=Input$("> ") Print ">" Print "Type server port :" GetPort=Input("> ") GetResult=HostGame(GetGameName$,GetName$,GetPort) If GetResult > 0 Then Print Error$(GetResult) Goto EndOfApp End If End If While KeyDown(1)=False Select UdpRuntime() Case 5 Print Error$(5) Exit End Select Wend If UdpStream>0 Then CloseUDPStream(UdpStream) If TcpStream>0 Then CloseTCPServer(TcpStream) .EndOfApp Print "" Print "Application end" Print "Press any key..." WaitKey() Function UdpRuntime() RecvUDPMsg(UdpStream) MsgLength=ReadAvail(UdpStream) If MsgLength > 0 Then ;Read header bytes GetMode=ReadByte(UdpStream) GetPing=ReadByte(UdpStream) ;Read Msg Properties UdpIp=UDPMsgIP(UdpStream) UdpPort=UDPMsgPort(UdpStream) ;Process ping/pong If GetPing=True Then ;Send Pong Msg WriteUdpByte(UdpStream,3) WriteUdpByte(UdpStream,0) SendUDPMsg(UdpStream,UdpIp,UdpPort) End If Select GetMode Case 1 ;[SERVER] If UdpServer=True ;Is a Server If Udp=False Then If UdpBusy=False Then ;Connection Accepted. Save IP and Port UdpBusy=True UdpSaveIp=UdpIp UdpSavePort=UdpPort ;Send Accept echo WriteUdpByte(UdpStream,2) ; Msg ID WriteUdpByte(UdpStream,0) ; Ping Status WriteUdpString(UdpStream,UdpServerName$) SendUDPMsg(UdpStream,UdpIp,UdpPort) Print "User Connecting ..." Else ;Server Is Busy send error WriteUdpByte(UdpStream,4) ; Msg ID WriteUdpByte(UdpStream,0) ; Ping Status WriteUdpByte(UdpStream,2) ; Msg Data SendUDPMsg(UdpStream,UdpIp,UdpPort) End If Else ;Server is already in progress. ;Send Error Msg WriteUdpByte(UdpStream,4) ; Msg ID WriteUdpByte(UdpStream,0) ; Ping Status WriteUdpByte(UdpStream,1) ; Msg Data SendUDPMsg(UdpStream,UdpIp,UdpPort) End If Else ;Is a Client ;Send Protocol error msg WriteUdpByte(UdpStream,4) ; Msg ID WriteUdpByte(UdpStream,0) ; Ping Status WriteUdpByte(UdpStream,3) ; Msg Data SendUDPMsg(UdpStream,UdpIp,UdpPort) End If Case 2 ;[CLIENT] If UdpServer=True ;Is a Server If Udp=False Then If UdpBusy=True Then ;Grab client username UdpClientName$=ReadUdpString$(UdpStream) Print "Client is called '" + UdpClientName$ + "'" ;Send Notice plus ping WriteUdpByte(UdpStream,5) WriteUdpByte(UdpStream,1) WriteUdpString(UdpStream,UdpGameName$) SendUDPMsg(UdpStream,UdpSaveIp,UdpSavePort) ;Save Ping Data UdpPing=True UdpPingStart=MilliSecs() End If End If Else ;Is a Client If Udp=False Then If UdpBusy=True Then Print "Connection Accepted!" ;Connection allowed. Save IP and Port UdpSaveIp=UdpIp UdpSavePort=UdpPort ;Get Server username from msg UdpServerName$=ReadUdpString$(UdpStream) Print "Server is called '" + UdpServerName$ + "'" ;Send Client Accept+User+Ping WriteUdpByte(UdpStream,2) ; Msg ID WriteUdpByte(UdpStream,1) ; Ping Status WriteUdpString(UdpStream,UdpClientName$) SendUDPMsg(UdpStream,UdpIp,UdpPort) ;Save Ping Data UdpPing=True UdpPingStart=MilliSecs() End If End If End If Case 3 ; [CLIENT / SERVER] ;Recieved a pong (ping is complete). If UdpPing=True Then If UdpBusy=True Then If Udp=False Then ;Connection complete Udp=True UdpBusy=False ;Close Tcp Name Lookup server If UdpServer=True Then CloseTCPServer(TcpStream) Print "" Color 255,0,0 Print "Link Completed" Color 255,255,255 End If End If UdpPing=False UdpPingResult=MilliSecs()-UdpPingStart Print "Ping " + UdpPingResult + "ms" End If Case 4 ; [CLIENT / SERVER] Print "ERROR : " +Error$(ReadByte(UdpStream)) Case 5 ; [CLIENT] If UdpServer=False Then If Udp=True Then Color 75,75,255 Print ReadUdpString$(UdpStream) Color 255,255,255 End If End If End Select End If ;Update Timer If UdpTime=True Then If MilliSecs()-UdpTimeStart > UdpTimeOut Then UdpTimeStart=MilliSecs() If UdpTimeRetry > 0 Then UdpTimeRetry=UdpTimeRetry-1 ;Attempts events If UdpServer=True Then ;Server Else ;Client If Udp=True Then ;Connected Else ;Not Connected If UdpBusy=True Then ;Attempting Connect ;Send another attempt at connect WriteByte(UdpStream,1) WriteByte(Udpstream,0) SendUDPMsg(UdpStream,UdpSaveIp,UdpSavePort) Print "Retrying ..." End If End If End If Else ;TIMEOUT! If UdpServer=True Then ;Server Else ;Client If Udp=True Then ;Connected Else ;Not Connected If UdpBusy=True Then ;No Resposne when attempting to connect Return 5 End If End If End If End If End If End If ;No errors Return 0 End Function Function HostGame(GameName$,UserName$,Port) UdpServer=True UdpBusy=False Udp=False UdpServerName$=UserName$ UdpGameName$=GameName$ ;Make sure Game Name is longer than 0 If Len(UdpGameName$)=0 Then UdpGameName$="Unnamed Game" ;Create Streams UdpStream=CreateUDPStream(Port) TcpStream=CreateTCPServer(Port) If UdpStream=0 Or TcpStream=0 Then ;TCP or UDP is in use on the given port ;Return Error number If UdpStream>0 Then CloseUDPStream(UdpStream) If TcpStream>0 Then CloseTCPStream(TcpStream) Return 4 End If ;Server was started correctly Print "Server Started!" Return 0 End Function Function JoinGame(UserName$,Address$,LocalPort,ServerPort) UdpServer=False UdpBusy=True Udp=False UdpClientName$=UserName$ ;Create Streams UdpStream=CreateUDPStream(LocalPort) If UdpStream=0 Then Return 4 ;Setup timer for retry attempt UdpTime=True UdpTimeStart=MilliSecs() UdpTimeOut=5000 UdpTimeRetry=3 ;Write Connect string UdpSaveIp=GetIpInt(Address$,ServerPort) UdpSavePort=ServerPort WriteByte(UdpStream,1) WriteByte(Udpstream,0) SendUDPMsg(UdpStream,UdpSaveIp,UdpSavePort) Print "Connecting to "+DottedIP$(UdpSaveIp) ;Join was done correctly Return 0 End Function Function ReadUdpString$(Stream) MakeString$="" While Eof(Stream)=False MakeString$=MakeString$+Chr$(ReadByte(Stream)) Wend Return MakeString$ End Function Function WriteUdpByte(Stream,TheByte) WriteByte(Stream,TheByte) End Function Function WriteUdpString(Stream,TheString$) For I=1 To Len(TheString$) WriteUdpByte(Stream,Asc(Mid$(TheString,I,1))) Next End Function Function GetIpInt(Address$,Port=0) ;Check for character type Found=False For I=1 To Len(Address$) GetAsc=Asc(Mid$(Address$,I,1)) If GetAsc < 48 Or GetAsc > 57 If GetAsc <> 46 Then Found=True Exit End If End If Next If Found=False Then Return GetIpFromDotted(Address$) Else Return GetIpFromName(Address$,Port) End If End Function Function GetIpFromDotted(inputip$) break1 = Instr(inputIP$,".") : break2 = Instr(inputIP$,".",break1+1) : break3 = Instr(inputIP$,".",break2+1) add1 = Mid(inputIP$,1,break1-1):add2 = Mid(inputIP$,break1+1,break2-1):add3 = Mid(inputIP$,break2+1,break3-1):add4 = Mid(inputIP$,break3+1) ipreturn=(add1 Shl 24) + (add2 Shl 16) + (add3 Shl 8) + add4 Return ipreturn End Function Function GetIpFromName(Name$,Port) Print "Looking up address " + Name$ + "..." Delay 100 OpenStream=OpenTCPStream(Name$,Port) If OpenStream=0 Then Return 0 RealAddress=TCPStreamIP(OpenStream) CloseTCPStream(OpenStream) Return RealAddress End Function |
Comments
None.
Code Archives Forum