24

All the "server" example in scala use actors, reactors etc...

Can someone show me how to write a dead simple echo server and client, just like the following python example of Server and Client:

# A simple echo server 
import socket 

host = '' 
port = 50000 
backlog = 5 
size = 1024 
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 
s.bind((host,port)) 
s.listen(backlog) 
while 1: 
    client, address = s.accept() 
    data = client.recv(size) 
    if data: 
        client.send(data) 
    client.close()

# A simple echo client 
import socket 

host = 'localhost' 
port = 50000 
size = 1024 
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 
s.connect((host,port)) 
s.send('Hello, world') 
data = s.recv(size) 
s.close() 
print 'Received:', data
M1L0U
  • 1,175
  • 12
  • 20
Andriy Drozdyuk
  • 58,435
  • 50
  • 171
  • 272

5 Answers5

39

You can do following within standard library:

// Simple server
import java.net._
import java.io._
import scala.io._

val server = new ServerSocket(9999)
while (true) {
    val s = server.accept()
    val in = new BufferedSource(s.getInputStream()).getLines()
    val out = new PrintStream(s.getOutputStream())

    out.println(in.next())
    out.flush()
    s.close()
}

// Simple client
import java.net._
import java.io._
import scala.io._

val s = new Socket(InetAddress.getByName("localhost"), 9999)
lazy val in = new BufferedSource(s.getInputStream()).getLines()
val out = new PrintStream(s.getOutputStream())

out.println("Hello, world")
out.flush()
println("Received: " + in.next())

s.close()

If you don't mind using extra libraries, you might like Finagle.

Przemek Pokrywka
  • 2,219
  • 17
  • 23
  • It doesn't run past the line "val (in, out) =..." in client. – Andriy Drozdyuk Jun 24 '11 at 13:31
  • Try to save the examples to separate files and run them using scala command. For some unknown reason it hangs when pasted directly in REPL (or even loaded via :load command). – Przemek Pokrywka Jun 24 '11 at 17:47
  • 1
    I know why it works from files and not in REPL. Funny thing :) When you execute: val in = new BufferedSource(s.getInputStream()).getLines() REPL will try to show you the value of the expression. However this is not possible until the echo-server replies, and server waits for request currently. If you shut down the server, client will resume. – Przemek Pokrywka Jun 24 '11 at 18:04
  • If you want to run the client in the REPL, inline "in" val - delete line with "val in" declaration, then replace "in" reference with "new BufferedSource(s.getInputStream()).getLines()" – Przemek Pokrywka Jun 24 '11 at 20:34
  • Thanks, I'm going to give this a try tomorrow! – Andriy Drozdyuk Jun 25 '11 at 01:46
  • Made "in" val lazy in echo client, so REPL won't evaluate it prematurely. Now you can paste the client's code directly to REPL. – Przemek Pokrywka Jun 25 '11 at 14:31
  • I tried your code with scala 2.9, both in REPL and in .scala files (both with lazy and without) - but it produces no output. It just hangs there... :-( – Andriy Drozdyuk Jun 26 '11 at 20:43
  • Strange - could you kill -3 it (or jstack where can be obtained by jps -ml)? Obtained thread dump would show, where it hangs. – Przemek Pokrywka Jun 28 '11 at 15:57
  • I'm afraid I am running windows, so no "kill"s for me :p – Andriy Drozdyuk Jun 28 '11 at 19:07
  • Ok, then at the command prompt just type: "jps -ml" (this will tell you the PID) and then "jstack PID|more" (replace PID with the number given by jps for scala.tools.nsc.MainGenericRunner). You'll see where it hangs. Jps and JStack are shipped with JDK. – Przemek Pokrywka Jun 28 '11 at 19:53
  • Nice and simple, exactly what we wanted! Not sure if this is meant to be complete or what version of scala this is for, but compiling with `scalac` gave me: `error: expected class or object definition`. Worked fine wrapped under `object...` though. – Nagev Feb 05 '21 at 18:18
  • @Nagev thanks for kind words! It was meant to work in a Scala REPL, for example https://ammonite.io/ for Scala 2.x. For a non-REPL usage you need to wrap it into an object with a main method, yes. – Przemek Pokrywka Feb 06 '21 at 19:40
3

I just wrote a blog post about using Akka IO and Iteratees to create a simple command based socket server.

Maybe it could be of interest.

http://leon.radley.se/2012/08/akka-command-based-socket-server/

Leon Radley
  • 7,596
  • 5
  • 35
  • 54
2

You would have to use Java Sockets. I found a nice example of a Scala Socket Server/Client at: http://www.scala-lang.org/node/55

Marcelo
  • 11,218
  • 1
  • 37
  • 51
  • I think the question is about maximum simplicity, and in Scala you can get simpler actually (see my answer). People value Python for low-ceremony-high-gain approach and Scala is often more concise. – Przemek Pokrywka Jun 20 '11 at 21:25
  • @Przemek Yes, I know. I just linked to an example so that @drozzy would get an idea and implement the Echo Server and Client himself, in the process learning more about Scala. – Marcelo Jun 20 '11 at 21:48
  • Ok :) Recently I've had some discussion on "Python vs Scala" topic, which fully convinced me, that choosing the best examples is crucial in promoting a language. Though that made me forget, that some people (like you) might just want to help :) (as opposed to promoting) – Przemek Pokrywka Jun 20 '11 at 22:14
  • @Przemek I am a Java programmer myself and would not mind being convinced to choose Scala over Java, any resources to help me with this? – Marcelo Jun 20 '11 at 22:34
  • There are books: http://www.scala-lang.org/node/959 - some come in free editions: http://www.readwriteweb.com/hack/2011/04/5-free-b-books-and-tutorials-o.php Good luck! – Przemek Pokrywka Jun 21 '11 at 05:28
  • finagle links are 404 – harschware Feb 13 '15 at 00:14
0

You can use netty java library. Here is an example usage in Scala:

https://github.com/mcroydon/scala-echo-server

Generally you need to use Java Socket API. In this example Java Socket API are used, but the whole server is wrapped in Actor in order to process clients in separate thread and not to block acceptor thread (the same thing you will normally do in Java, but you will use threads directly).

tenshi
  • 26,268
  • 8
  • 76
  • 90
0

Josh Suereth recently posted an example of an NIO echo server using scalaz Iteratees. Requires the scalaz library

oxbow_lakes
  • 133,303
  • 56
  • 317
  • 449