A library for C# designed to help speed up the development of UDP networking apps.
A library for C# designed to help speed up the development of UDP networking apps.
(copied from the README, because of time constraints irl)
UdpClub is a C# library, which acts as a wrapper around the UdpClient class, with a few extra utilities. UdpClub automatically handles parsing byte data into packages for you, as well as RPC calls and a standardized way to create network packages for your project.
The project features a demo project known as āChatAppā, it can be found as one of the attachments on the 1.0.0 release tab on GitHub.
18 minutes? Surely I mustāve done more than fix kicking.. maybe the time I spent testing the Messaging App and updating the README heavily played into this time. But thatās small stuff. I have made one final fix, which should hopefully mark the demo app as complete.. kicking! Previously, as you may have seen in my previous devlog, kicking didnāt refresh the users list on the server-side, now it does. This should hopefully prevent the app from getting rejected for bugs. Guess weāll have to wait and see though. Time to ship! Thank you to everyone who has read even one line of these devlogs.
Log in to leave a comment
Well, what can I say.. the demo is done? At least everything I thought to test is functioning well, so⦠might ship this project really soon. Itās been fun! Been super cool to make my own wrapper library for the C# UdpClient. Who knows, maybe I can actually use this project for games or something, I mean I got package and RPC Handling implemented. Of course, I would like to clean up the codebase sometime, but, who knows when Iāll get to that.
So the final bits of polish I added since last devlog was getting rid of duplicate āx left the chat.ā messages when a user got kicked and adding a āx GOT KICKEDā message to the server client.
Happy coding :D
I swear to god I always have the weirdest bugs with the weirdest solutions in this project. Anyways! Almost 4 hours elapsed, letās see what I managed to do in that timeā¦
The server application no longer just blocks inputs to the startup window, instead it now shows a window similar to the client interface, except you canāt message. But to make up for that, if you are the server, you can kick clients! Why? It means more features, which means more time to work on this project. So thereās that.
So, this plays directly into the moderation feature. The issue was that I couldnāt find a way to force a remote UdpClient to disconnect, hence I had to make a little workaround. The ForceDisconnectPackageis built into UdpClub now and it automatically disconnects a client from the server. Beware though, it doesnāt work on servers.
I fixed a major bug that has been plaguing the demo project since I got the Client UI to work, duplicate names in the users list. And I finally figured out how to fix it, I tried everything from locking the memberList variable (since it might be an issue with multi-threading), but to no effect. However, delaying the function by 50ms seems to do the trick. I figured this out when I was debugging the project and couldnāt replicate the bug at all, whereas it would constantly appear without the debugger. Why? I have no idea lmao.
I put a few neat things in the attachments this time around, first off the obvious, the server UI. But I also put in the new code for adding a member with locking (just in case) and timeouts, and a demonstration of what kicking looks like!
Have a nice day and happy coding!
Log in to leave a comment
After having loads of fun using the UdpClub demo with my friend who lives all the way in America, I had made a realization that I shouldāve made long ago⦠the error handling is practically non-existent. Thatās a pretty major issue if you ask me. So I finally did something about it. Now, whenever PackageHandler has an error, it throws an exception and keeps running. This is mainly so applications donāt freeze when an error such as a SocketException occur. I could handle this better, and I probably will. But for now this rudimentary system is very helpful for me. Especially since it lets the demo run more consistently.
Log in to leave a comment
Few changes since I last checked in an hour ago.. So whatās new?
So.. turns out you can use markdown on here? An extension that was showcased in the show and tell made me aware of this. Itās super cool, tbh. Gonna be using this way more.
Now, when a user joins or leaves the server, a little message is sent into the chat! Making it feel less empty and also letting you sort of timestamp when someone leaves/rejoins. Neat, isnāt it? I think it is. If you feel another way, well then I quite frankly donāt know what to tell you. Moving on!
As the previous header, and the screenshot that I definitely put a lot of thought into, may imply⦠messenging works! Now you can send messages to other clients and have a little chat. Well, ok, not really in this case, I donāt wanna engage in port-forwarding right now, so I have only tested it on localhost with myself, but it works pretty darn well from what Iāve tested, except one bug where the user list duplicates an entry, dunno where itās wrong, but Iāll fix it eventually!
RunOnServer parameter in RpcPackagesThis was originally intended to be a bug fix for the Leave Message duplicating before I figured out the actual cause, but since I feel like somebody will find utility in it, might as well leave this little scrappy feature in. Enjoy, potential users of this library, you can now force a server to never run an RPC.
During testing I had an issue where the server froze up a few times. The cause? C# throws an exception when you try to invoke an Action that hasnāt been subscribed to, and somehow my code doesnāt output that exception (maybe cuz itās running on a different thread? idk). In any case, that is fixed now, and the server runs as well as it can. How good is that? I have no idea. Gotta do more testing.
Log in to leave a comment
Alrighty, small check in again.. I managed to implement users syncing, so now when you connect to the server, you get a small RPC call that gives you a list of every user that is currently connected to the server. Now I just need to make it, so that on the backend, the user leave message is properly communicated. Maybe I should switch it from an RPC to a Package then. Who knows. For now, I do mainly wanna get messaging working, because thatās the main selling point of this app.
Log in to leave a comment
Ok, ok. So, I didnāt want to deal with the termianl for the demo project anymore, so I kinda just.. rebuilt the entire thing in Windows Forms. Right now very little works, you can start a server instance and a client instance. The client can input their username and then the main messaging UI loads. Nothing crazy, just took a bit because Riderās UI builder doesnāt like me. But, hey, soon I can build some logic for sending messages, sending the user list to new clients (right now if the user ātestā logged in after āaveryā, only āaveryā would see both users in the user list). I also need to implement leaving, because right now that doesnāt have any implementation at all⦠Also a server UI.. After that? Not sure. Maybe I can add moderator operations to the server UI. Guess weāll see. I am also kinda writing this in a rush, so excuse me if my sentence structure changes mid-sentence. See you and happy coding!
Log in to leave a comment
Alrighty, so, Iām a bit hazey on what I actually did in this almost hour and a half timeframe, so here goes nothing.
I simplified the invokation of RPCs! Now you just have to run RpcManager.BroadcastRpc(ā¦) to run your RPC on the network. Itās nothing special, practically just a wrapper that makes an RpcPackage and throws it through PackageHandler, but itās nice to have nonetheless. In bigger news, I got kind-of sick of always having to reference ātypeof(MyPackage)ā when making a package class, so, I made the GenericPackage class, which acts as an abstraction layer on top of the regular BasePackage. It allows you to create packages way quicker and easier, since now you only have to specify your packetās class name once, and the GenericPackage does the rest! Itās so nice to have, especially since a large bug I had in the demo project was because I wrote ātypeof(AuthPacket)ā instead of ātypeof(AuthReturnPacket)ā in my AuthReturnPacket class, making it so the AuthReturn never got interpreted. The new package structure, using the generic package class, is so much cleaner (see second screenshot). Donāt worry, though, you can still manually create a class on top of BasePackage if youād like, nobodyās stopping you. And thatās about it, I think. Super fun working on this project for a bit and Iām getting a tad bit closer to shipping. I also hope I can show this project off at the Show and Tell tonight, guess weāll see. See ya!
Log in to leave a comment
We got a logo now! Whipped up this cool little network of circles, because I thought itād fit the project really nicely. Also I fixed a bug where every RPC in the project would get called if you called a single one. i.e. if you had the RPCs āUserJoinMessageā, āUserLeaveMessageā and āUserEmojiReactā and you called the RPC for āUserJoinMessageā it would actually trigger all 3 RPCs. That is now fixed, silly me. Also I have swapped a few more debug-prints for the DebugPrintln function. Yay! Happy coding and thanks for reading!
Log in to leave a comment
RPCs work! I repeat, they fully work! I have freaking done it! I am so happy with myself for managing to fix RPCs so quickly - only took me 24 minutes, huh. I have also made some changes to some not-so-relevant parts of the source code, like replacing lots of the aforementioned statements that I wrapped in ā#if DEBUGā to use my DebugPrint/DebugPrintln functions. But, back to the main course, I managed to figure out a nasty bug in parsing RPCs that would cause the network thread to hang indefinitely because of an unhandled exceptions (thanks, Rider Debugger for pointing that out to me..)
And.. yeah! I guess itās time to clean up some code, write the demo project and maybe look into more parameters? Who knows! What I know for sure is that Iām gonna blast Good Kid music now. Cheers!
Log in to leave a comment
Another day, another⦠four hours of work? Damn. I didnāt even realize. Alright, well, hereās what I spent my time doing today, and what I will continue to do because I want this project to freaking work.
So! I worked on a little demo project, because I planned on shipping an initial release of UdpClub soon. But thereās a slight issue with that, the app I want to make for my demo is a basic messaging app between multiple clients, only issue is that I want to include things like a welcome message when a user joins and some other stuff where an RPC with a parameter would be lovely. Only issue is⦠I canāt do that. For something as simple as a welcome message I just simply want to be able to call an RPC and have it invoke everywhere. Annoyingly, I was too lazy to implement that when my mind understood the awful code I wrote! Now I have to dive back in and debug it. And thatās what Iāve been doing! Well, ok, I did also work on the basic demo project, but who cares about that. Anyhow, during these four hours of debugging my code I have noticed how incredibly fragile the system is and how badly I want to remake it to be way clearer to debug and use, so, uh⦠RPC rewrite today? Maybe? Who knows. Though, today I will probably only get RPCs with one parameter working and like.. replace all my manual #if DEBUG /* print */ #endif statements with an abstraction, which I called āDebugPrintā. Anyways, thatās basically all. Letās hope that I can get this resolved ASAP when Iām home and not bothered by school, the new NullReferenceException is definitely promising⦠Cheers!
Log in to leave a comment
Not a lot of changes for right now, but thatās mainly, because I spent my time making an EXE for SWP so the ship doesnāt get rejected again.
But, I implemented a small feature.. loopbacks! A loopback lets you specify if the RPC Package should return to the sender once the client sends it to the server, this is useful so there is less confusion about if you should run the RPC function locally as well, or if the package comes from the server-side. It also has practical usages, but I canāt think of any examples off the top of my head.
Next up is (hopefully) documentation and cleanup of the existing RPC handling code. Letās see how that goes.
Happy coding and thank you for reading!
Log in to leave a comment
⦠so I spent 3 hours implementing RPCs (Remote Procedure Calls), and boy oh boy⦠itās a mess, like most things in this!
So, letās dive into it, shall we?
At first I began with writing a RPC Attribute class, plain and simple, afterwards a small RPCManager to ensure that I can easily call RPCs from anywhere. Then followed a small RPC Package to make it easy for the server to communicate that the clients should execute a function, all well and good⦠Until it came to implementing how youāre supposed to run the function. Granted, I took the easy way out: only allow static methods. But I donāt want that to be the case forever, I want this to eventually run on object instances too, but thatās gonna take a bit for me to do. Probably past the time limit of this whole Flavortown thing, so, screw it. Anyways, so after implementing all that, I was met with an issue: RPCs werenāt registering. So, what did I mess up? Well I had the call to subscribe my RPC to the RPCManager in the RPCAttribute constructor, should work, right? Well, the developers of roslyn (the C# compiler) decided to throw me a giant āF**k you,ā because the constructor for an Attribute is never called until you somehow reference the RPC via MethodInfo.GetCustomAttributes() and whatnot⦠suffice to say it took me a bit to figure out.
But, hey, I finally did it. Now you can register static functions are RPCs with a specific ID and you can easily call āem through the server, now all I have left to do is make the communication system with the RPCPacket work in a way that a client can request to execute a RPC to the server and then the server can spread that message to other clients.. and I should definitely get parameters working. But, I think first Iāll focus on cleaning up this steaming mess of redundant calls and whatnot, and heavy documentation, right now only god and I know what this code does, not very sustainable.
Anyhow, happy coding!
gotta make this quick, sorry..
thanks for reading!
I feel like one of the best programmers of all time right now - my complex workaround for making a dynamic package library somehow worked on the first try! I managed to finally make it so you can easily initialize a UdpClientApp or UdpServerApp and send packages from it! And it just⦠works! As long as you make a registry for the packages which adds them to PackageHandler.Packages using PackageHandler.RegisterPacket(ā¦) but thatās beside the point. What I mean to say is that, the fundemental principle of my application is done, a more simplistic way to send and parse data packets over a network. Can it be optimized? 100%. Will I optimize it? Perhaps, weāll see how much time I have for that until I ship the project. For now though, I will happily enjoy this win and dance around like a silly goober to āNa Na Na (Na Na Na Na Na Na Na Na Na)ā by My Chemical Romance. See ya, and thank you, you lovely individual, for reading this!
Oh, also, if you care to check out what I made and you canāt find the GitHub repo, you can find the project source code at: https://github.com/averyocean65/UdpClub/
Log in to leave a comment
⦠so turns out the fix for the communication issue between the Client and Server was simply because the client was using the IP EndPoint used in āUdpClient.Receive(ā¦)ā to communicate messages, which apparently doesnāt work for sending stuff to the server - the more you know! Thanks C#.
Anyhow, the issue is fixed now using a simple if-else statement lol. Took me about 3 minutes to figure out.
I also worked on a package class as well as a PackageMap, I also took baby steps in creating the PackageHandler. Now, unfortunately, I am not sure how to build a modular system for building and identifying packets, so Iāll have to get back to my mental drawing board until something comes to mind.
Log in to leave a comment
I finally got a basic framework running to send data between a server and client via the UDP protocol. I am extremely happy to see that I got it up and running from only an hour of work. Unfortunately there is a bug in the package handling, as the server and client should constantly send packages to each other, so I have to do some debugging to see whatās going wrong. Very strong start though! Hope I can get the Package and Package Manager classes implemented tomorrow if I manage to iron this bug out.
Log in to leave a comment