Chat server: Difference between revisions

m (→‎{{header|Perl 6}}: Remove TODO, bug has been fixed for some time)
Line 1,412:
run(server,8000)
</lang>
 
=={{header|Kotlin}}==
{{trans|Java}}
<lang kotlin>import java.io.BufferedReader
import java.io.IOException
import java.io.InputStreamReader
import java.io.OutputStreamWriter
import java.io.Writer
import java.net.ServerSocket
import java.net.Socket
import java.util.ArrayList
import java.util.Collections
 
class ChatServer private constructor(private val port: Int) : Runnable {
private val clients = ArrayList<Client>()
 
private val onlineListCSV: String
@Synchronized get() {
val sb = StringBuilder()
sb.append(clients.size).append(" user(s) online: ")
for (i in clients.indices) {
sb.append(if (i > 0) ", " else "").append(clients[i].clientName)
}
return sb.toString()
}
 
override fun run() {
try {
val ss = ServerSocket(port)
while (true) {
val s = ss.accept()
Thread(Client(s)).start()
}
} catch (e: Exception) {
e.printStackTrace()
}
}
 
@Synchronized
private fun registerClient(client: Client): Boolean {
for (otherClient in clients) {
if (otherClient.clientName!!.equals(client.clientName!!, ignoreCase = true)) {
return false
}
}
clients.add(client)
return true
}
 
private fun deRegisterClient(client: Client) {
var wasRegistered = false
synchronized(this) {
wasRegistered = clients.remove(client)
}
if (wasRegistered) {
broadcast(client, "--- " + client.clientName + " left ---")
}
}
 
private fun broadcast(fromClient: Client, msg: String) {
// Copy client list (don't want to hold lock while doing IO)
var clients: List<Client> = Collections.emptyList()
synchronized(this) {
clients = ArrayList(this.clients)
}
for (client in clients) {
if (client.equals(fromClient)) {
continue
}
try {
client.write(msg + "\r\n")
} catch (e: Exception) {
e.printStackTrace()
}
 
}
}
 
inner class Client internal constructor(private var socket: Socket?) : Runnable {
private var output: Writer? = null
var clientName: String? = null
 
override fun run() {
try {
socket!!.sendBufferSize = 16384
socket!!.tcpNoDelay = true
val input = BufferedReader(InputStreamReader(socket!!.getInputStream()))
output = OutputStreamWriter(socket!!.getOutputStream())
write("Please enter your name: ")
var line: String
while (true) {
line = input.readLine()
if (null == line) {
break
}
if (clientName == null) {
line = line.trim { it <= ' ' }
if (line.isEmpty()) {
write("A name is required. Please enter your name: ")
continue
}
clientName = line
if (!registerClient(this)) {
clientName = null
write("Name already registered. Please enter your name: ")
continue
}
write(onlineListCSV + "\r\n")
broadcast(this, "+++ $clientName arrived +++")
continue
}
if (line.equals("/quit", ignoreCase = true)) {
return
}
broadcast(this, "$clientName> $line")
}
} catch (e: Exception) {
e.printStackTrace()
} finally {
deRegisterClient(this)
output = null
try {
socket!!.close()
} catch (e: Exception) {
e.printStackTrace()
}
 
socket = null
}
}
 
@Throws(IOException::class)
internal fun write(msg: String) {
output!!.write(msg)
output!!.flush()
}
 
internal fun equals(client: Client?): Boolean {
return (client != null
&& clientName != null
&& client.clientName != null
&& clientName == client.clientName)
}
}
 
companion object {
@JvmStatic
fun main(args: Array<String>) {
var port = 4004
if (args.isNotEmpty()) {
port = Integer.parseInt(args[0])
}
ChatServer(port).run()
}
}
}</lang>
 
=={{header|Nim}}==
1,452

edits