简体   繁体   中英

Share one ServerSocket connection to client between multiple threads in Kotlin

I am making a server application in Kotlin, and the server does following things:

  1. Bind a ServerSocket port let's say 10001. This port accepts TCP connection from clients (Users). Thread used. Works now as intended.

  2. It also opens and Binds a local port 10002 from localhost only. This port allows external application in local host to connect, and communicate as manager thread.

  3. It initiate a remote connection to another server in UDP, translates TCP data from port 10001 to UDP by restructuring the data pack and visa-versa. This thread is being created by the thread running port 10001 connection on-demand above at #1.

Now, we have 3 connections as shown below (Manager & User connections are two different Threads):

Manager(10002) --> | Kotlin | --> Remote Server
User(10001) <-----> | Server | <-- (UDP Port)

So, I want to send some commands from Manager Thread to User Thread buy specifying certain tread identifier, and that will initiate a code block in User thread to send some JSON data to user terminal.

And one of the command from Manager thread will start a remote server connection(UDP, assume a thread too) to communicate and translate data between User Thread and the remote server connection.

So in this case, how do I manage the communication between threads especially between Manager and User thread?

I have been able to create treads to accept User side connections, and it works fine now.

val socketListener_User = ServerSocket(10001)
socketListener_User.use {
    while (true) {
        val socket_User = socketListener_User.accept()
        thread(start = true) {
            /** SOME CODE HERE **/
            /** THIS PART IS FOR USER THREAD **/
        }
    }
}

The user can send data at any time to Server as well as Manager. So the server shall be on standby for both side, and neither of them shall block each other.

It should be similar to instant messenger server, but usually IMs store data in external database and trigger the receiver to read, isn't it?

And now I believe there must be some way to establish communications channels between treads to do above tasks which I have not figured out.

After digging some docs, I ended up using cascaded MutableMaps to store the data needed to be shared between threads

In main class file, before main(), I declared vals for the data storage maps.

val msgToPeers : MutableMap<String, <Int, <String, String>>> = HashMap()
// Format: < To_ClientID, < Sequence_Num, < From_ClientID, Message_Body >>>

Next, in threads for each serversocket connection, create two sub threads

  • 1: Sender Thread
  • 2: Receiver Thread

In Sender Thread , construct the datamap, and add into "msgToPeers" by using

  • msgToPeers.set() or msgToPeers["$receiverClientID"] =.......

Then in Receiver Thread , run a loop to scan the map, and pick up whatever data you need only, and output to socketwriter.

Remember to use msgToPeers["receiverClientID"].remove(sequenceID) to empty the processed message before goes to next loop.

Oh, I also added a 50ms pause per loop as I needed to make sure that the sender threads to have enough time to queue the message list before the scanner takes the message and clear it.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM