mattschinkel Posted January 19, 2011 Share Posted January 19, 2011 Hi there, I'd like to make a UDP server. I need to be able to send data back to the client (whoever that is). I do not wish to specify the IP address/port of the client. This should be possible with UDP. I posted my non-working code below to show what I would like to do. After the client sends me any data, the server should reply with "Hello Client!") on the same socket. I would also like to allow multiple clients on my server. I'm a open source contributor trying to do networking on PIC microcontrollers with JalV2. Some of my work can be found here: http://www.justanotherlanguage.org/ Thanks, Matt. expandcollapse popup;;This is the UDP Server ;;Start this first HotKeySet("{ESC}", "quit") ; Start The UDP Services ;============================================== UDPStartup() ; Register the cleanup function. OnAutoItExitRegister("Cleanup") ; Bind to a SOCKET ;============================================== ;$socket = UDPBind("192.168.2.2", 251) $socket = UDPBind("192.168.1.11", 251) While 1 ;get UDP data from client $data = UDPRecv($socket, 50) If $data <> "" Then ;display incomming data MsgBox(0, "UDP DATA", $data, 1) ;send a reply message MsgBox("", "UDP DATA", "Sending: Hello Client!", 1) $status = UDPSend($socket, "Hello Client! ") If $status = 0 then MsgBox(0, "ERROR", "Error while sending UDP message: " & @error) Exit EndIf ;clear input data $data = "" EndIf sleep(100) WEnd Func quit() UDPCloseSocket($socket) UDPShutdown() exit EndFunc Link to comment Share on other sites More sharing options...
CodyBarrett Posted January 19, 2011 Share Posted January 19, 2011 things i noticed #1 MSGBOX() is a blocking function. ---Can't have it in a Loop and expect the script to continue after the MSGBOX() has been called. #2 after i looked through it twice: your MaxByteLen is only 50 ---maybe the limit needs to be more than that? #3 no client script ---where is the client script? [size="1"][font="Tahoma"][COMPLETED]-----[FAILED]-----[ONGOING]VolumeControl|Binary Converter|CPU Usage| Mouse Wrap |WinHide|Word Scrammbler|LOCKER|SCREEN FREEZE|Decisions Decisions|Version UDF|Recast Desktop Mask|TCP Multiclient EXAMPLE|BTCP|LANCR|UDP serverless|AIOCR|OECR|Recast Messenger|AU3C|Tik-Tak-Toe|Snakes & Ladders|BattleShips|TRON|SNAKE_____________________[u]I love the Helpfile it is my best friend.[/u][/font][/size] Link to comment Share on other sites More sharing options...
mattschinkel Posted January 20, 2011 Author Share Posted January 20, 2011 What do you mean where is the client script? As I said, I'd like to make a UDP server. The server should reply to the client with this code, using the same socket: $status = UDPSend($socket, "Hello Client! ") Link to comment Share on other sites More sharing options...
CodyBarrett Posted January 21, 2011 Share Posted January 21, 2011 ah. right, i had missed that. well, have you tried a ConsoleWrite () or some other form of NON blocking function to view the data that is being sent? [size="1"][font="Tahoma"][COMPLETED]-----[FAILED]-----[ONGOING]VolumeControl|Binary Converter|CPU Usage| Mouse Wrap |WinHide|Word Scrammbler|LOCKER|SCREEN FREEZE|Decisions Decisions|Version UDF|Recast Desktop Mask|TCP Multiclient EXAMPLE|BTCP|LANCR|UDP serverless|AIOCR|OECR|Recast Messenger|AU3C|Tik-Tak-Toe|Snakes & Ladders|BattleShips|TRON|SNAKE_____________________[u]I love the Helpfile it is my best friend.[/u][/font][/size] Link to comment Share on other sites More sharing options...
Pottery Posted January 21, 2011 Share Posted January 21, 2011 I think it's better to use TCP, even if it's for use over LAN. Here's a multi-client server you can edit to fit your needs: $iMaxConnections = 25 Global $iCurrentSocket = 0, $oListenSocket, $oConnectedSocket[$iMaxConnections] TCPStartup() $oListenSocket = TCPListen(@IPAddress1, 8044, $iMaxConnections) If $oListenSocket = -1 Then Exit While 1 $oConnectedSocket[$iCurrentSocket] = TCPAccept($oListenSocket) ConsoleWrite($oConnectedSocket[$iCurrentSocket]&@CR) If $oConnectedSocket[$iCurrentSocket] <> -1 Then $iCurrentSocket = $iCurrentSocket + 1 EndIf For $i = 0 To $iMaxConnections-1 If $oConnectedSocket[$i] <> -1 Or $oConnectedSocket[$i] <> "" Then $sResv = TCPRecv($oConnectedSocket[$i], 512) If $sResv <> "" Then ; EndIf EndIf Next Sleep(20) WEnd Link to comment Share on other sites More sharing options...
mattschinkel Posted January 22, 2011 Author Share Posted January 22, 2011 Thanks, but I am not interested in TCP at the moment. I am trying to write one UDP client program on PIC microcontrollers, and one UDP server program for PIC microcontrollers. I have already been able to make a UDP server on the microcontroller, and can correctly connect a Autoit UDP client to it. However, I cannot make a UDP server on Autoit. It is surprising that I can make UDP server on a 20mhz CPU, but I cannot do the same with Autoit on a PC. I am very aware that blocking delay's are not good, but it should work in the example given. I changed it to ConsoleWrite() and still does not work. After the Autoit program receives a UDP packet, it continuously loops printing "Sending: Hello Client!" in the console (it should only print that once), and does not actually send any packets. I am monitoring the network with Wireshark. Here is an image of the networking device I have connected to my 20mhz microcontroller http://cgi.ebay.com/NEW-ENC28J60-Network-Development-Board-Ethernet-Module-/320542004086?pt=LH_DefaultDomain_0&hash=item4aa1cad376 And there are some images of a microcontroller I am using on this page: http://www.justanotherlanguage.org/content/jallib/tutorials/tutorial_blink_a_led Matt. Link to comment Share on other sites More sharing options...
qsek Posted January 22, 2011 Share Posted January 22, 2011 (edited) Im not an expert in Protocols, but right now im trying to get known with it and had also trouble understanding the way to get UDP working two sided.Well, its quite simple: - you only can use UDPSend on a socket you created with UDPOpen - you can only use UDPRecv on a socket you created with UDPBindSo if you want that the "Server"(UDPBind/UDPRecv) communicate with the "Client"(UDPOpen/UDPSend)you have to also use UDPOpen/UDPSend on the server and UDPBind/UDPRecv on the client.TCP works different, once you created a socket with TCPOpen, you can send and recieve on this socket.Got me some F5's to understand that difference.But with this setup you even can use only one UDPport since its the fixed local port on each pc that is used for recieving and for sending AutoIt will use a random port.Example below:expandcollapse popup#Include <Misc.au3> _Singleton("QsekTCPEventServerSingleton") ;;This is the UDP Server ;;Start this first ; Start The UDP Services ;============================================== UDPStartup() ; Register the cleanup function. OnAutoItExitRegister("Cleanup") ; Bind to a SOCKET ;============================================== $recvSocket = UDPBind(@IPAddress1, 65532) If @error <> 0 Then Exit $sendSocket = UDPOpen("xxx.xxx.xxx.xxx", 65532); <---- Client IP here If @error <> 0 Then Exit While 1 sleep(10) $inc = UDPRecv($recvSocket, 50) If $inc <> "" Then Sleep(50) ConsoleWrite("SERVER> Recieved $data: "&$inc) $spl = StringSplit($inc,"|",2) If Not @error And IsArray($spl) And UBound($spl) = 3 Then If $spl[2] = @CRLF Then If $spl[0] = "HiImClient:i_got_number" Then ConsoleWrite("SERVER> processed number: "&$spl[1] & @CRLF& @CRLF) $status = UDPSend($sendSocket,"IAMSERVER:i_got_this_number_from_you|"&$spl[1]&"|"&@CRLF) If $status Then ;~ ConsoleWrite("SERVER> sending: '"&"IAMSERVER:i_got_this_number_from_you||"&$data&"|@CRLF'"&@CRLF) Else MsgBox(0, "ERROR", "Error while sending UDP message: " & @error) Exit EndIf EndIf $data = "" Else $data &= $inc EndIf EndIf EndIf WEnd Func Cleanup() UDPCloseSocket($recvSocket) UDPShutdown() EndFuncexpandcollapse popup;;This is the UDP Client ;;Start the server first ; Start The UDP Services ;============================================== UDPStartup() ; Register the cleanup function. OnAutoItExitRegister("Cleanup") ; Open a "SOCKET" ;============================================== $sendSocket = UDPOpen("xxx.xxx.xxx.xxx", 65532); <--- Server IP here If @error <> 0 Then Exit $recvSocket = UDPBind(@IPAddress1, 65532) If @error <> 0 Then Exit $ti = TimerInit() $n=0 $data = "" While 1 Sleep(10) $inc = UDPRecv($recvSocket, 100) If $inc <> "" Then ConsoleWrite("CLIENT > Recieved $data: "&$inc) $spl = StringSplit($inc,"|",2) If Not @error And IsArray($spl) And UBound($spl) = 3 Then If $spl[2] = @CRLF Then If $spl[0] = "IAMSERVER:i_got_this_number_from_you" Then ConsoleWrite("CLIENT > processed number: "&$spl[1] & @CRLF& @CRLF) ;~ $status = UDPSend($sendSocket,"IAMSERVER:i_got_this_number_from_you|"&$spl[1]&"|"&@CRLF) ElseIf $spl[0] = "other Command" Then ;~ ConsoleWrite("CLIENT > Answer from Server: "&$inc & @CRLF) EndIf $data = "" Else $data &= $inc EndIf EndIf EndIf If TimerDiff($ti) > 2000 Then $ti = TimerInit() $n = Random(1,99999,1) $status = UDPSend($sendSocket, "HiImClient:i_got_number|"&$n&"|"&@CRLF) If $status Then ConsoleWrite("CLIENT > sending: '"&"HiImClient:i_got_number|"&$n&"'@CRLF"&@CRLF) Else MsgBox(0, "ERROR", "Error while sending UDP message: " & @error) Exit EndIf EndIf WEnd Func Cleanup() UDPCloseSocket($sendSocket) UDPShutdown() EndFuncBut i yet have to figure out how to get the Client IP on the server.If the client sends data to server, the server must somehow get packets with the clients IP.why isnt there a function UDPGetClientIP($socket) or something? Edited January 22, 2011 by qsek Teamspeak 3 User Viewer - Quick and functional TS3 Query script, which shows online users.Cached Screenshot Deleter - Deletes older Fraps Screenshots if they exceed a specified limit.Unresolved Topics:Intercept and modify dragdrop text behaviour in scite Link to comment Share on other sites More sharing options...
bogQ Posted January 22, 2011 Share Posted January 22, 2011 @qsekUDPBind Return ValueSuccess: Returns an array : $array[1] contains the real socket, $array[2] contains the specified IP address and $array[3] contains the port. So if im not wrong $array[2] shud hold client incoming IP adress, never used UDP before so i hope that i did not misunderstood help file TCP server and client - Learning about TCP servers and clients connectionAu3 oIrrlicht - Irrlicht projectAu3impact - Another 3D DLL game engine for autoit. (3impact 3Drad related) There are those that believe that the perfect heist lies in the preparation.Some say that it’s all in the timing, seizing the right opportunity. Others even say it’s the ability to leave no trace behind, be a ghost.  Link to comment Share on other sites More sharing options...
qsek Posted January 22, 2011 Share Posted January 22, 2011 (edited) Thanks for the help bogQ, but: Success: Returns an array : $array[1] contains the real socket, $array[2] contains the specified IP address and $array[3] contains the port. So the "specified IP" for UDPBind is the one of the server. Its the one i put into --> UDPBind("xxx.xxx.xxx.xxx", 65532) I located the Source IP field in the Packet that is recieved from the server. But its in the IPv4 Frame. So i guess its one "level" higher than UDP. But it still should be stored somewhere. How to query this information? Update: Alright, once again the information was in the helpfile, but well hidden, so dont blame me UDPRecv ( socketarray, maxlen [, flag] ) flag [optional] Forces the function to return binary data if set to 1 (default is 0, and will auto detect between binary/string). Forces the function to return receive from IP/port if set to 2. Results are returned in an Array : [0] data, [1] from IP, [2] from Port. If you want both just use 3. Edited January 22, 2011 by qsek Teamspeak 3 User Viewer - Quick and functional TS3 Query script, which shows online users.Cached Screenshot Deleter - Deletes older Fraps Screenshots if they exceed a specified limit.Unresolved Topics:Intercept and modify dragdrop text behaviour in scite Link to comment Share on other sites More sharing options...
mattschinkel Posted January 22, 2011 Author Share Posted January 22, 2011 It works! I was able to make a proper UDP server. I suggest rewording the help file. Maybe even put an example, such as the following: expandcollapse popup;;This is the UDP Server ;;Start this first #Include <Array.au3> HotKeySet("{ESC}", "quit") ; Start The UDP Services ;============================================== UDPStartup() ; Register the cleanup function. OnAutoItExitRegister("Cleanup") ; Bind to a SOCKET ;============================================== $Socket = UDPBind("192.168.1.11", 251) While 1 ;get UDP data from client $Data = UDPRecv($Socket, 50,3) If IsArray($Data) Then ConsoleWrite($Data[0]) ConsoleWrite(@CRLF) ;create temp socket from incomming IP/PORT $SocketIn = UDPOpen($Data[1], $Data[2]) ;send a reply message ConsoleWrite("Sending reply: Hello Client!") $status = UDPSend($SocketIn, "Hello Client! ") If $status = 0 then MsgBox(0, "ERROR", "Error while sending UDP message: " & @error) Exit EndIf ;remove temp socket UDPCloseSocket($SocketIn) $Data[0] = 0 ConsoleWrite(@CRLF) ConsoleWrite(@CRLF) EndIf sleep(100) WEnd Func quit() UDPCloseSocket($Socket) UDPShutdown() exit EndFunc Link to comment Share on other sites More sharing options...
mattschinkel Posted January 22, 2011 Author Share Posted January 22, 2011 The current example under UDPRecv says this: ;;This is the UDP Server ;;Start this first Although, this is not a server since it is not serving the client. Matt. Link to comment Share on other sites More sharing options...
mattschinkel Posted January 25, 2011 Author Share Posted January 25, 2011 One more complaint about the above working code I posted. I can now reply to the client on the client's port. The destination port does match the client port. However, the server's source port in this reply message is random and does not match. This source port should be the same as our server port. In my sample, the reply message source port should be 251. example with current procedures: 1. server opens on port 251 2. client sends message to server on destination port 251, source port 1234(random but ok) 3. server sends reply. destination port 1234, source port 5678(random NOT ok) How it should be: 1. server opens on port 251 2. client sends message to server on destination port 251, source port 1234(random but ok) 3. server sends reply. destination port 1234, source port 251(not random, same as server port, good!) To fix this, I suggest UDPSend() should have an optional parameter for source port. Do you agree? How may I go about getting this implemented? Matt. Link to comment Share on other sites More sharing options...
CodyBarrett Posted January 25, 2011 Share Posted January 25, 2011 whats wrong with the UDPBind port Param? or UDPOpen port Param? You specify the ports in those functions to create a socket. (not necessarily needed for udp...) [size="1"][font="Tahoma"][COMPLETED]-----[FAILED]-----[ONGOING]VolumeControl|Binary Converter|CPU Usage| Mouse Wrap |WinHide|Word Scrammbler|LOCKER|SCREEN FREEZE|Decisions Decisions|Version UDF|Recast Desktop Mask|TCP Multiclient EXAMPLE|BTCP|LANCR|UDP serverless|AIOCR|OECR|Recast Messenger|AU3C|Tik-Tak-Toe|Snakes & Ladders|BattleShips|TRON|SNAKE_____________________[u]I love the Helpfile it is my best friend.[/u][/font][/size] Link to comment Share on other sites More sharing options...
mattschinkel Posted January 25, 2011 Author Share Posted January 25, 2011 whats wrong with the UDPBind port Param? or UDPOpen port Param?You specify the ports in those functions to create a socket. (not necessarily needed for udp...)What's wrong is that the UDPBind/UDPOpen only allow you to specify one port which is either the source port or the destination port. You cannot specify both. I guess UDPBind/UDPOpen procedures need another parameter (not UDPSend as I suggested prevously).This is quite necessary for UDP. As explained above, when the server responds to the client, the server's source port must be correct. It must be correct so the client can identify the socket correctly.I checked how a normal DNS server (UDP) responds to a client in wireshark, and I am not able to do it the same response with Autoit. In other words, I would not be able to create a proper DNS server with Autoit.Matt. Link to comment Share on other sites More sharing options...
CodyBarrett Posted January 26, 2011 Share Posted January 26, 2011 i've never had problems with UDP's destination/source ports before, i always specifiy UDPBIND (serverip,serverport) UDPOPEN (serverip,serverport) i always use the same port for both... however it is simply the lack of error checking the protocol has that gives me an error. its strange that you have this problem. [size="1"][font="Tahoma"][COMPLETED]-----[FAILED]-----[ONGOING]VolumeControl|Binary Converter|CPU Usage| Mouse Wrap |WinHide|Word Scrammbler|LOCKER|SCREEN FREEZE|Decisions Decisions|Version UDF|Recast Desktop Mask|TCP Multiclient EXAMPLE|BTCP|LANCR|UDP serverless|AIOCR|OECR|Recast Messenger|AU3C|Tik-Tak-Toe|Snakes & Ladders|BattleShips|TRON|SNAKE_____________________[u]I love the Helpfile it is my best friend.[/u][/font][/size] Link to comment Share on other sites More sharing options...
mattschinkel Posted January 27, 2011 Author Share Posted January 27, 2011 i've never had problems with UDP's destination/source ports before, i always specifiy UDPBIND (serverip,serverport) UDPOPEN (serverip,serverport) i always use the same port for both... however it is simply the lack of error checking the protocol has that gives me an error. its strange that you have this problem.You would not have this issue unless you create a proper UDP server. It will work, and it will work good, but it will not work correctly. Can you change my code above to act correctly?With UDP you must create your own error checking. I like UDP because of my project. UDP is a small and simple protocol that uses less resources.Matt. Link to comment Share on other sites More sharing options...
mattschinkel Posted January 29, 2011 Author Share Posted January 29, 2011 Where and how may I modify the Autoit UDP library and procedures? I would like to try to fix this issue myself. Matt. Link to comment Share on other sites More sharing options...
jvanegmond Posted January 29, 2011 Share Posted January 29, 2011 Where and how may I modify the Autoit UDP library and procedures? I would like to try to fix this issue myself. Matt.You can not do that, and there is no need to do that. The library has excellent error checking and exposes these errors to the end-user in AutoIt via the @error macro. github.com/jvanegmond Link to comment Share on other sites More sharing options...
mattschinkel Posted January 29, 2011 Author Share Posted January 29, 2011 Is Autoit is open source? If so, where is the UDP source? I do not wish to expose errors to users, I'm sure Autoit contributors have some standard way of implementing changes. I would like to contribute. Matt. Link to comment Share on other sites More sharing options...
CodyBarrett Posted January 29, 2011 Share Posted January 29, 2011 (edited) what exactly is your issue again? maybe its not even an autoit issue... you stated that the arrays giving you are random source ports? try this instead... tell us whats wrong with it. [EDIT] well i changed my mind, my solution (maybe already thought of, but why not hardcoding the server's ports? $port = 251 (why) i could be dead wrong, and i'm not afraid to say i am, but in my networking class at school my teacher mentioned how microsoft opens a port to recv and opens a different port to send, so wouldn't the port that was being opened to send be the one that is recorded in the packet? microsoft randomizes each created port right? just specify to which port that is opened for which function ie the recv port, $port. just have them both the same on both client and server. (i will look like a tard if i'm wrong, heres hoping) expandcollapse popup;;This is the UDP Server ;;Start this first #Include <Array.au3> HotKeySet("{ESC}", "quit") ; Start The UDP Services ;============================================== UDPStartup() ; Register the cleanup function. OnAutoItExitRegister("Quit") ; Bind to a SOCKET ;============================================== $port = 251 ;~ $Socket = UDPBind("192.168.1.11", 251) $Socket = UDPBind("192.168.1.11", $port) While 1 ;get UDP data from client $Data = UDPRecv($Socket, 50,3) If IsArray($Data) Then ConsoleWrite($Data[0]) ConsoleWrite(@CRLF) ;create temp socket from incomming IP/PORT ;~ $SocketIn = UDPOpen($Data[1], $Data[2]) $SocketIn = UDPOpen($Data[1], $port) ;send a reply message ConsoleWrite("Sending reply: Hello Client!") $status = UDPSend($SocketIn, "Hello Client! ") If $status = 0 then MsgBox(0, "ERROR", "Error while sending UDP message: " & @error) Exit EndIf ;remove temp socket UDPCloseSocket($SocketIn) $Data[0] = 0 ConsoleWrite(@CRLF) ConsoleWrite(@CRLF) EndIf sleep(100) WEnd Func quit() UDPCloseSocket($Socket) UDPShutdown() exit EndFunc Edited January 29, 2011 by CodyBarrett [size="1"][font="Tahoma"][COMPLETED]-----[FAILED]-----[ONGOING]VolumeControl|Binary Converter|CPU Usage| Mouse Wrap |WinHide|Word Scrammbler|LOCKER|SCREEN FREEZE|Decisions Decisions|Version UDF|Recast Desktop Mask|TCP Multiclient EXAMPLE|BTCP|LANCR|UDP serverless|AIOCR|OECR|Recast Messenger|AU3C|Tik-Tak-Toe|Snakes & Ladders|BattleShips|TRON|SNAKE_____________________[u]I love the Helpfile it is my best friend.[/u][/font][/size] Link to comment Share on other sites More sharing options...
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now