7
\$\begingroup\$

Your challenge, should you choose to accept it, is simple:

Implement RFC 862, also known as the Echo Protocol:

The Echo protocol

An echo service simply sends back to the originating source any data it receives.

TCP Based Echo Service

One echo service is defined as a connection based application on TCP. A server listens for TCP connections on TCP port 7. Once a connection is established any data received is sent back. This continues until the calling user terminates the connection.

UDP Based Echo Service

Another echo service is defined as a datagram based application on UDP. A server listens for UDP datagrams on UDP port 7. When a datagram is received, the data from it is sent back in an answering datagram.

Scoring

  • The score is one point for every byte of code as encoded in UTF-8 or a language-specific code page, whichever is smaller.
  • If the program incompletely implements RFC 862 by providing only UDP or only TCP, the score is doubled.
  • If the program incorrectly implements RFC 862 by either using a port other than 7 or by dropping or transforming certain bytes due to language limitations or corner cutting, the score is quadrupled. (This stacks with the preceding point if applicable.)
  • If the program is invalid, the score is ω.

Rules

A valid program:

  • Does not use standard loopholes.
  • Per connection:
    • Accepts connections and receive incoming data.
    • Sends outgoing data in an amount that is always less than or equal to the amount of data received.
  • Does not invoke programs external to itself. (Spawning children to deal with multiple connections is fine, spinning up inetd or its local equivalent is not.)
  • Does not use library functions specifically designed to start and maintain an echo service.

This is code golf, so lowest score wins.

\$\endgroup\$
  • 2
    \$\begingroup\$ AKA: HTTP Cat program. \$\endgroup\$ – cat Apr 27 '16 at 12:39
  • 2
    \$\begingroup\$ Infinity is , not ω \$\endgroup\$ – anatolyg Apr 27 '16 at 14:57
  • 1
    \$\begingroup\$ @anatolyg isn't a number, ω is; and the score needs to be a number. \$\endgroup\$ – Williham Totland Apr 27 '16 at 15:03
  • 4
    \$\begingroup\$ Why don't you just say if the program is invalid it's disqualified.. \$\endgroup\$ – Patrick Roberts Apr 27 '16 at 15:38
  • 2
    \$\begingroup\$ I think the rule about port 7 is pointless. In general, you'll need to be root to use ports <1024, regardless of language. I assume that this challenge is allowing entries to run as root with no extra penalty. \$\endgroup\$ – Digital Trauma Apr 27 '16 at 17:48
3
\$\begingroup\$

JavaScript (Node.js) 102 Bytes (51 * 2)

require("net").createServer(s=>s.pipe(s)).listen(7)

You can add UDP for a total of 132 bytes, as seen below:

require("net").createServer(s=>s.pipe(s)).listen(7),(u=require("dgram").createSocket("udp4")).on("message",msg=>u.send(msg)).bind(7)

Was tested on node.js v5.2.0

Make sure to run with sudo on Unix descendants (OS X, Linux, etc.)

\$\endgroup\$
4
\$\begingroup\$

Python, 299 295 265 263

from threading import*
from socket import*
a='',7;S=socket
u=S(2,2);u.bind(a)
def U():
 while 1:u.sendto(*u.recvfrom(4**8))
Thread(None,U).start()
def C(c,x):
 while c.send(c.recv(1)):1
s=S(2,1);s.bind(a);s.listen(1)
while 1:Thread(None,C,args=s.accept()).start()

handles both udp and tcp.

@MorganThrapp helped saving 33 (!) chars

\$\endgroup\$
  • \$\begingroup\$ You can also get rid of the parens on ('',7). Also, move s=S(2,2);s.bind(a) out of U to save another byte. \$\endgroup\$ – Morgan Thrapp Apr 27 '16 at 15:45
  • \$\begingroup\$ A UDP datagram may have up to 65,507 bytes, so 999 is not enough; I suggest 4**8. \$\endgroup\$ – Anders Kaseorg Apr 27 '16 at 16:00
  • \$\begingroup\$ well, afaik in practice the max size for udp packets is more around 500 bytes .. \$\endgroup\$ – dieter Apr 27 '16 at 16:03
  • \$\begingroup\$ No, in practice it’s 1472 for non-fragmented datagrams (1500 ethernet MTU − 20 byte IP header − 8 byte UDP header), but fragmented datagrams or jumbograms can be larger. \$\endgroup\$ – Anders Kaseorg Apr 27 '16 at 16:04
  • \$\begingroup\$ @Anders Karseorg And much more if you use en.wikipedia.org/wiki/IP_over_Avian_Carriers :) - anyway I put 4**8 and you give me an upvote, ok ? \$\endgroup\$ – dieter Apr 27 '16 at 16:08
3
\$\begingroup\$

Racket, 231

(thread(λ()(do([l(tcp-listen 7)])(#f)(let-values([(i o)(tcp-accept l)])(copy-port i o)))))((λ(s b)(udp-bind! s #f 7)(do()(#f)(let-values([(n h p)(udp-receive! s b)])(udp-send-to s h p b 0 n))))(udp-open-socket)(make-bytes 65535))

TCP and UDP.

The TCP echo server uses a handy Racket procedure named copy-port that copies ports in the background, managed by Racket, instead of by the programmer. That also means I don't have to spin off a thread for each client, only for the listener (so I can start the UDP listener on the main thread).

\$\endgroup\$

Not the answer you're looking for? Browse other questions tagged or ask your own question.