Write a program or function that listens for incoming TCP traffic on port N. It offers a simple service: it calculates sum of IP address fields of incoming connection and returns.
Program or function reads integer N from arguments or stdin. It listens to incoming TCP connections on port N. When someone connects to that port, the program calculates sum of its IP address fields and sends it back to the client with trailing newline and closes connection.
- Port number N is a valid port, and 210 < N < 215
- Trailing newline can be either
\n
or\r\n
- You can use either IPv4 or IPv6. Since IPv6 addresses are written in hexadecimal form, you must also provide result in same format, for example
2001:0db8:0000:0042:0000:8a2e:0370:7334 => 12ecd
.
This is code-golf. Standard rules and loopholes apply.
Example
You run your server with ./server 1234
. The server is now running and waiting for connections on port 1234. Then a client from 127.0.0.1
connects to your server. Your server performs a simple calculation: 127+0+0+1 => 128
and sends the result to the client (with trailing newline): 128\n
. Then server closes connection and waits for next client.
Leaderboard
var QUESTION_ID=76379,OVERRIDE_USER=20569;function answersUrl(e){return"https://api.stackexchange.com/2.2/questions/"+QUESTION_ID+"/answers?page="+e+"&pagesize=100&order=desc&sort=creation&site=codegolf&filter="+ANSWER_FILTER}function commentUrl(e,s){return"https://api.stackexchange.com/2.2/answers/"+s.join(";")+"/comments?page="+e+"&pagesize=100&order=desc&sort=creation&site=codegolf&filter="+COMMENT_FILTER}function getAnswers(){jQuery.ajax({url:answersUrl(answer_page++),method:"get",dataType:"jsonp",crossDomain:!0,success:function(e){answers.push.apply(answers,e.items),answers_hash=[],answer_ids=[],e.items.forEach(function(e){e.comments=[];var s=+e.share_link.match(/\d+/);answer_ids.push(s),answers_hash[s]=e}),e.has_more||(more_answers=!1),comment_page=1,getComments()}})}function getComments(){jQuery.ajax({url:commentUrl(comment_page++,answer_ids),method:"get",dataType:"jsonp",crossDomain:!0,success:function(e){e.items.forEach(function(e){e.owner.user_id===OVERRIDE_USER&&answers_hash[e.post_id].comments.push(e)}),e.has_more?getComments():more_answers?getAnswers():process()}})}function getAuthorName(e){return e.owner.display_name}function process(){var e=[];answers.forEach(function(s){var r=s.body;s.comments.forEach(function(e){OVERRIDE_REG.test(e.body)&&(r="<h1>"+e.body.replace(OVERRIDE_REG,"")+"</h1>")});var a=r.match(SCORE_REG);a&&e.push({user:getAuthorName(s),size:+a[2],language:a[1],link:s.share_link})}),e.sort(function(e,s){var r=e.size,a=s.size;return r-a});var s={},r=1,a=null,n=1;e.forEach(function(e){e.size!=a&&(n=r),a=e.size,++r;var t=jQuery("#answer-template").html();t=t.replace("{{PLACE}}",n+".").replace("{{NAME}}",e.user).replace("{{LANGUAGE}}",e.language).replace("{{SIZE}}",e.size).replace("{{LINK}}",e.link),t=jQuery(t),jQuery("#answers").append(t);var o=e.language;/<a/.test(o)&&(o=jQuery(o).text()),s[o]=s[o]||{lang:e.language,user:e.user,size:e.size,link:e.link}});var t=[];for(var o in s)s.hasOwnProperty(o)&&t.push(s[o]);t.sort(function(e,s){return e.lang>s.lang?1:e.lang<s.lang?-1:0});for(var c=0;c<t.length;++c){var i=jQuery("#language-template").html(),o=t[c];i=i.replace("{{LANGUAGE}}",o.lang).replace("{{NAME}}",o.user).replace("{{SIZE}}",o.size).replace("{{LINK}}",o.link),i=jQuery(i),jQuery("#languages").append(i)}}var ANSWER_FILTER="!t)IWYnsLAZle2tQ3KqrVveCRJfxcRLe",COMMENT_FILTER="!)Q2B_A2kjfAiU78X(md6BoYk",answers=[],answers_hash,answer_ids,answer_page=1,more_answers=!0,comment_page;getAnswers();var SCORE_REG=/<h\d>\s*([^\n,]*[^\s,]),.*?(\d+)(?=[^\n\d<>]*(?:<(?:s>[^\n<>]*<\/s>|[^\n<>]+>)[^\n\d<>]*)*<\/h\d>)/,OVERRIDE_REG=/^Override\s*header:\s*/i;
body{text-align:left!important}#answer-list,#language-list{padding:10px;width:290px;float:left}table thead{font-weight:700}table td{padding:5px}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <link rel="stylesheet" type="text/css" href="//cdn.sstatic.net/codegolf/all.css?v=83c949450c8b"> <div id="answer-list"> <h2>Leaderboard</h2> <table class="answer-list"> <thead> <tr><td></td><td>Author</td><td>Language</td><td>Size</td></tr></thead> <tbody id="answers"> </tbody> </table> </div><div id="language-list"> <h2>Winners by Language</h2> <table class="language-list"> <thead> <tr><td>Language</td><td>User</td><td>Score</td></tr></thead> <tbody id="languages"> </tbody> </table> </div><table style="display: none"> <tbody id="answer-template"> <tr><td>{{PLACE}}</td><td>{{NAME}}</td><td>{{LANGUAGE}}</td><td>{{SIZE}}</td><td><a href="{{LINK}}">Link</a></td></tr></tbody> </table> <table style="display: none"> <tbody id="language-template"> <tr><td>{{LANGUAGE}}</td><td>{{NAME}}</td><td>{{SIZE}}</td><td><a href="{{LINK}}">Link</a></td></tr></tbody> </table>
-
1\$\begingroup\$ Is it allowed to use inetd/xinetd or similar? \$\endgroup\$Digital Trauma– Digital Trauma2016年03月28日 18:17:34 +00:00Commented Mar 28, 2016 at 18:17
-
94\$\begingroup\$ I like this, since it's a golfing challenge that golfing languages are unlikely to be very good at. \$\endgroup\$izzyg– izzyg2016年03月28日 18:54:21 +00:00Commented Mar 28, 2016 at 18:54
-
9\$\begingroup\$ Not only is it amazing that a TCP server is apparently a very easy program to write, I am thoroughly floored at the fact that it's getting golfed for fun. I'll just go back to struggling with FizzBuzz like an imbecile. \$\endgroup\$MonkeyZeus– MonkeyZeus2016年03月29日 19:50:22 +00:00Commented Mar 29, 2016 at 19:50
-
18\$\begingroup\$ @isaacg It's only time before someone finds the TCP server built-in in Mathematica \$\endgroup\$Downgoat– Downgoat2016年03月29日 22:19:46 +00:00Commented Mar 29, 2016 at 22:19
-
3\$\begingroup\$ @MonkeyZeus To be fair, you will not see any good TCP server here. Making a reliable, scalable TCP server that handles all the intricacies of TCP (and your application protocol) well is a bit harder :D Though it certainly helps that the protocol is exceedingly simple - you don't even need to read the stream, something that I've seen broken in too many TCP servers to count :D \$\endgroup\$Luaan– Luaan2016年03月30日 09:11:30 +00:00Commented Mar 30, 2016 at 9:11
40 Answers 40
Bash + netcat + ss + ..., (削除) 65 (削除ここまで) 60 characters
nc -lp1ドル -c'ss src :'1ドル'|awk \0ドル=\5ドル|tr .: +#|bc'
exec 0ドル 1ドル
Not a serious solution, was just curious about this possibility.
Thanks to:
- ninjalj for suggesting the
awk
based filtering (-5 characters)
Sample run:
(terminal 1)
bash-4.3$ ./ip-reduce.sh 8080
(terminal 2)
bash-4.3$ nc localhost 8080
128
bash-4.3$ telnet localhost 8080
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
128
Connection closed by foreign host.
On Ubuntu you can get nc
from netcat-traditional (no, netcat-openbsd is not good) and ss
from iproute2.
-
24\$\begingroup\$ Why do you say it isn't a serious solution? As long as it works as expected I see no reason why it shouldn't be considered serious. It's also the shortest by a pretty significant margin at the moment. \$\endgroup\$Alex A.– Alex A.2016年03月28日 16:43:06 +00:00Commented Mar 28, 2016 at 16:43
-
\$\begingroup\$ The biggest concern against it appeared during discussion with @JesseSielaff when I learned that on systems with configured IPv6, socket related information may be formatted differently. Have no such system to test it. For which I'm thinking whether would be more correct to turn it into CW. \$\endgroup\$manatwork– manatwork2016年03月28日 17:02:07 +00:00Commented Mar 28, 2016 at 17:02
-
3\$\begingroup\$ My understanding of the spec is that you have to support IPv4 or IPv6, not both. So as long as it works for IPv4, not supporting IPv6 shouldn't matter, I would think. \$\endgroup\$Alex A.– Alex A.2016年03月29日 04:11:10 +00:00Commented Mar 29, 2016 at 4:11
-
1\$\begingroup\$ @AlexA. At least I think my question says so. Should I clarify it? \$\endgroup\$Hannes Karppila– Hannes Karppila2016年03月29日 15:30:05 +00:00Commented Mar 29, 2016 at 15:30
-
\$\begingroup\$ @HannesKarppila, your question is clear. The possible issue is that my solution may require the operating system to be configured in a particular way to be able to run. So I'm worry because it may fail if IPv6 is configured, regardless whether I handle it or not. Someone who has IPv6 configured could tell it for sure... \$\endgroup\$manatwork– manatwork2016年03月29日 15:55:44 +00:00Commented Mar 29, 2016 at 15:55
Linux ELF/x86, 146 bytes
00000000 7f 45 4c 46 01 00 00 00 5a 0e 00 00 5a 5e eb 10 |.ELF....Z...Z^..|
00000010 02 00 03 00 0c 50 eb 10 0c 50 eb 10 04 00 00 00 |.....P...P......|
00000020 5e 53 43 53 52 89 e1 b0 66 3d 20 00 01 00 cd 80 |^SCSR...f= .....|
00000030 97 55 6b ed 0a 01 c5 ac 2c 30 79 f6 43 0f cd 01 |.Uk.....,0y.C...|
00000040 dd 55 89 e1 6a 10 51 6a 10 51 57 89 e1 b0 66 cd |.U..j.Qj.QW...f.|
00000050 80 43 43 b0 66 cd 80 01 64 24 08 89 e1 43 b0 66 |.CC.f...d$...C.f|
00000060 cd 80 89 c1 93 8d 74 24 1b 99 fd ac 01 c2 e2 fb |......t$........|
00000070 89 f7 b0 0a aa 91 92 f6 f1 86 c4 04 30 aa 42 c1 |............0.B.|
00000080 e8 08 75 f3 42 89 f9 41 b0 04 cd 80 b0 06 cd 80 |..u.B..A........|
00000090 eb c9 |..|
00000092
Includes a 52-byte ELF header, a 32-byte program header, 111 bytes of program code + 3 bytes of code for skipping around inside the headers.
Information on how to create tiny ELF executables can be found at breadbox's "A Whirlwind Tutorial on Creating Really Teensy ELF Executables for Linux".
Linux/i386 uses the socketcall(2)
multiplex system call, which takes in ebx
the specific socket call (the SYS_*
macros from /usr/include/linux/net.h
), and in ecx
a pointer to the argument area of the original library call.
Some things done to keep the executable small:
- It assumes registers are zeroed on entry, which Linux does, but is not required by the ELF standard (the only requirement is that on entry
EDX
points to a finalization funtion (useful for executables loaded by the dynamic linker) or is NULL). - It assumes on launch (typically by a shell) the only open file descriptors are 0, 1, and 2. Which means that the listening socket will be fd 3, and the accepted socket will be fd 4.
- It assumes there are exactly 2 arguments (including
argv[0]
). - The same stack space is reused for the calls to
bind(2)
,listen(2)
andaccept(2)
. - To skip over the
phentsize
andphnum
fields, a byte is prepended, turning into aCMP
operation which takes thephentsize
andphnum
fields as an immediate (trick shamelessly stolen from breadbox's solution to 123 in anarchy golf). - x86 string operations
LODS
(load into accumulator and increment/decrement source index) andSTOS
(store from accumulator and increment/decrement destination index) are nice for short code. XCHG EAX, reg
is 1-byte, compared toMOV EAX, reg
, which takes 2 bytes.CDQ/CLTD
(sign-extendEAX
intoEDX:EAX
) can be used as a 1-byte way to zero theEDX
register.BSWAP
is useful for implementinghtons()
.
Nasm source:
BITS 32 ;
; ELF HEADER -- PROGRAM HEADER
; ELF HEADER ; +-------------+
DB 0x7f,'E','L','F' ; | magic | +--------------------+
; | | | |
; PROGRAM HEADERS ; | | | |
DD 1 ; |*class 32b | -- | type: PT_LOAD |
; |*data none | | |
; |*version 0 | | |
; |*ABI SysV | | |
DD 0xe5a ; offset = vaddr & (PAGE_SIZE-1); |*ABI vers | -- | offset |
; | | | |
entry: pop edx ; edx = 2 (argc) ; |*PADx7 | -- | vaddr = 0x10eb5e5a |
pop esi ; discard argv[0] ; | | | |
jmp short skip ; | | | |
DW 2 ; | ET_EXEC | -- |*paddr LO |
DW 3 ; | EM_386 | -- |*paddr HI |
DD 0x10eb500c ; |*version | -- | filesz |
DD 0x10eb500c ; | entry point | -- | memsz |
DD 4 ; | ph offset | -- | flags: RX |
; | | | |
skip: pop esi ; esi = argv[1] ; |*sh offset | -- |*align |
socket: push ebx ; default protocol (0) ; | | | |
inc ebx ; | | | |
push ebx ; SOCK_STREAM (1) ; | | | |
push edx ; AF_INET (2) ; |*flags | +--------------------+
mov ecx, esp ; | |
mov al, 0x66 ; |*ehsize |
DB 0x3d ; cmp eax,0x10020 ; | |
DW 32 ; | phentsize |
DW 1 ; | phnum |
; | |
int 0x80 ; socket(2, 1, 0) ; |*shentsize |
xchg edi, eax; edi = sockfd, eax = 0 ; |*shnum |
push ebp ; INADDR_ANY ; | |
; | |
mult: imul ebp, 10 ; \_ ; |*shstrndx |
add ebp, eax; > ; | |
lodsb ; > ; +-------------+
sub al,'0' ; >
jns mult ; / ebp = atoi(argv[1]) ; bind stack frame
; +-----------------------+
endmul: inc ebx ; SYS_BIND (2) ; | INADDR_ANY |
; +->| AF_INET | htons(port) |
bswap ebp ; | +-----------------------+
add ebp, ebx ; AF_INET (2), htons(port) ; | | 16 |
push ebp ; | +-----------------------+
; | | dummy |
mov ecx, esp ; | +-----------------------+
push 16 ; addrlen ; | | 16 |
push ecx ; dummy value ; | +-----------------------+
push 16 ; addrlen ; +--| addr |
push ecx ; addr ; +-----------------------+
push edi ; sock ; | sockfd |
mov ecx, esp ; +-----------------------+
mov al, 0x66
int 0x80 ; bind(sockfd, addr, addrlen)
; accept stack frame
; +-----------------------+
listen: ;mov byte [esp+8],1 ; | INADDR_ANY |
inc ebx ; +->| AF_INET | htons(port) |
inc ebx ; SYS_LISTEN (4) ; | +-----------------------+
mov al, 0x66 ; |+>| 16 |
int 0x80 ; listen(sockfd, backlog) ; || +-----------------------+
; || | dummy |
add [esp+8], esp ; || +-----------------------+
accept: mov ecx, esp ; |+-| &addrlen |
inc ebx ; SYS_ACCEPT (5) ; | +-----------------------+
mov al, 0x66 ; +--| addr |
int 0x80 ; accept(sockfd, addr, &addrlen); +-----------------------+
; | sockfd |
mov ecx, eax ; ecx = 4 ; +-----------------------+
xchg ebx, eax ; ebx = acceptfd, eax = 000000xx
lea esi, [esp+27] ; point to the IP part of struct sockaddr_in
cdq
std ; reverse direction for string operations
addip: lodsb ; \_
add edx, eax ; > edx = sum of 4 IP bytes
loop addip ; /
mov edi, esi ; reuse struct sockaddr_in as scratch buffer
mov al, 10 ; '\n'
stosb
xchg ecx, eax ; ecx = 10
xchg eax, edx ; edx = 0, eax = sum
divide: div cl ; \_
xchg al, ah ; >
add al,0x30 ; >
stosb ; > sprintf(scratch, "%d", sum)
inc edx ; >
shr eax, 8 ; >
jnz divide ; /
write: inc edx ; ndigits + 1 ('\n')
mov ecx, edi
inc ecx
mov al,4
int 0x80 ; write(acceptfd, scratch, scratchlen)
close: mov al, 6
int 0x80 ; close(acceptfd)
jmp accept
-
4\$\begingroup\$ This answer is way underappreciated. \$\endgroup\$cat– cat2016年07月07日 18:14:26 +00:00Commented Jul 7, 2016 at 18:14
C#, (削除) 284 (削除ここまで) (削除) 283 (削除ここまで) (削除) 282 (削除ここまで) (削除) 278 (削除ここまで) (削除) 274 (削除ここまで) 254 bytes
class A{static int Main(string[]a){var b=new System.Net.Sockets.TcpListener(int.Parse(a[0]));b.Start();for(;;){var c=b.AcceptTcpClient();var d=c.Client.LocalEndPoint.Serialize();new System.IO.StreamWriter(c.GetStream()).WriteLine(d[4]+d[5]+d[6]+d[7]);}}}
Classic example of a basic C# TCP server. Testing:
Terminal 1:
$ ./Q76379.exe 1029
Terminal 2:
$ telnet localhost 1029
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
128
Connection closed by foreign host.
Firefox:
-
7\$\begingroup\$ You can save 1 Byte by using
int Main
instead ofvoid Main
. As the program never returns the compiler doesn't require areturn
statement. \$\endgroup\$raznagul– raznagul2016年03月29日 09:45:07 +00:00Commented Mar 29, 2016 at 9:45 -
\$\begingroup\$ And no, it doesn't leak. It's actually pretty deterministic about releasing resources as well. Also, the argument to
Start
is optional, saving another character. \$\endgroup\$Luaan– Luaan2016年03月30日 08:53:56 +00:00Commented Mar 30, 2016 at 8:53 -
\$\begingroup\$ @Luaan Yeah, that was left over from debugging. \$\endgroup\$LegionMammal978– LegionMammal9782016年03月30日 10:17:38 +00:00Commented Mar 30, 2016 at 10:17
-
\$\begingroup\$ Also, you could use
using
on theTcpClient
, which will save you three more characters (use the{}
from thefor
), and doing the same with theStreamWriter
should save one more. \$\endgroup\$Luaan– Luaan2016年03月30日 11:13:55 +00:00Commented Mar 30, 2016 at 11:13 -
\$\begingroup\$ @Luaan I need to explicitly
Flush
theStreamWriter
to make it work properly. \$\endgroup\$LegionMammal978– LegionMammal9782016年03月30日 11:16:42 +00:00Commented Mar 30, 2016 at 11:16
NodeJS, (削除) 146 (削除ここまで) (削除) 134 (削除ここまで) 127 bytes
require('http').createServer((q,s)=>s.end(eval(0+q.socket.remoteAddress.replace(/^.*:|\./g,'+'))+'\n')).listen(process.argv[2])
I finally get to post a NodeJS answer! IPv4 only right now.
Sample execution: node script.js 1024
. From another terminal:
$ curl 127.0.0.1:1024
128
-
2\$\begingroup\$ I count 127 bytes right now, although you can get it down to 126 by swapping out
'\n'
with a template string containing a literal newline. \$\endgroup\$Mwr247– Mwr2472016年03月30日 00:08:55 +00:00Commented Mar 30, 2016 at 0:08 -
\$\begingroup\$ Wouldn't this fail the requirements because your creating a HTTP server , I mean, it's technically a TCP server, but couldn't you just use the TCP module and save yourself a character? \$\endgroup\$bren– bren2016年04月02日 19:07:33 +00:00Commented Apr 2, 2016 at 19:07
Tcl, 92
- 1 byte saved thanks to @DonalFellows.
proc s {c a p} {puts $c [expr [string map .\ + $a]]
close $c}
socket -server s $argv
vwait f
Fairly self-explanatory:
socket -server s $argv
creates a listening socket on the port specified in the arguments.
Every time a new connection arrives, the proc s
is called, with channel, source-address and source-port as parameters. string map
substitutes .
for +
in the source address, and expr
arithmetically evaluates the result, which is then puts
back to the connection channel c
.
vwait
runs an event loop to catch the incoming connection events.
Credit to @DonalFellows for the following:
Here's a version that handles IPv6 (requires Tcl 8.6; most of the extra length is due to producing a hex response):
Tcl, 109
proc s {c a p} {puts $c [format %x [expr 0x[string map :\ +0x0 $a]]]
close $c}
socket -server s $argv
vwait f
-
2\$\begingroup\$ Using
apply
doesn't seem to save anything. Nor can you usetcl::mathop::+ {*}[split $a .]
as that's slightly longer. Nor can you shave anything from option names. But supporting IPv6 is pretty trivial to add, and only costs a few bytes of code more (and then aregsub
-based approach is just as long). \$\endgroup\$Donal Fellows– Donal Fellows2016年03月30日 23:06:41 +00:00Commented Mar 30, 2016 at 23:06 -
\$\begingroup\$ ahhh, Tcl / Tcl-DP ... amazing bunch of tools. (in the '90s a professor showed us we could write a network-distributed Excel (with a grid, and including formulas evaluation!) shared among several persons with (iirc) 4 (short) lines for the server and 5 for the clients... \$\endgroup\$Olivier Dulac– Olivier Dulac2016年03月31日 17:22:51 +00:00Commented Mar 31, 2016 at 17:22
-
\$\begingroup\$
proc s {c a p}
do you really need all that whitespace? \$\endgroup\$cat– cat2016年04月08日 13:41:18 +00:00Commented Apr 8, 2016 at 13:41 -
1\$\begingroup\$ @cat yes, it is needed. It is by nature in Tcl. Between
s
and{
it is like a comma for arguments of theproc
procedure — For the better or the worse, in Tcl, everything is a string, so even the wordproc
to indicate a function, is not a keyword, but becomes a function itself. Spaces inc a p
are like commas for the arguments of thes
procedure. Amazing there's an high level language with only 12 syntax rules; it even led some people to write papers on building processors directly interpreting Tcl! Want more info? Search Scott Thibault Supporting Tcl in Hardware and Tcl on Board. \$\endgroup\$sergiol– sergiol2025年05月08日 07:56:32 +00:00Commented May 8 at 7:56
Groovy (削除) 133 (削除ここまで), (削除) 125 (削除ここまで), (削除) 93 (削除ここまで), 89
new ServerSocket(args[0]as int).accept{it<<(it.inetAddress.address as int[]).sum()+"\n"}
IPv4 only, probably.
Ungolfed:
new ServerSocket(args[0]as int).accept{
it << (it.inetAddress.address as int[]).sum()+"\n"
}
Testing:
$ telnet localhost 9000
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
128
Connection closed by foreign host.
-
1\$\begingroup\$
.toInteger()
→as int
ands.inetAddress.address*.toInteger()
→(s.inetAddress.address as int[])
. And there is an extra space after.with
. \$\endgroup\$manatwork– manatwork2016年03月28日 17:33:41 +00:00Commented Mar 28, 2016 at 17:33 -
\$\begingroup\$ @manatwork thx! Updated. \$\endgroup\$Will Lp– Will Lp2016年03月28日 18:13:26 +00:00Commented Mar 28, 2016 at 18:13
Python 3, (削除) 170 (削除ここまで) (削除) 166 (削除ここまで) 147 bytes
from socket import*
s=socket()
s.bind(("",int(input())))
s.listen()
while 1:
c,a=s.accept()
c.send(b"%d\n"%eval(a[0].replace(".","+"))),c.close()
Takes port on stdin
, IPv4 only. Works on GNU/Linux (and, I assume, most other unices), which automatically expands "" to "0.0.0.0", not sure about Windows though.
-
2\$\begingroup\$ You could save several bytes. Firstly, spaces in
import *
and, SOCK_STREAM
are unnecessary. Also, the send line could be written more efficiently asc.send(b"%d\n"%eval(a[0].replace(".","+")))
. \$\endgroup\$Hannes Karppila– Hannes Karppila2016年03月28日 12:35:58 +00:00Commented Mar 28, 2016 at 12:35 -
2\$\begingroup\$ @HannesKarppila oh, thanks. forgot about the spaces, the eval hack is pretty cool though. \$\endgroup\$sammko– sammko2016年03月28日 12:40:38 +00:00Commented Mar 28, 2016 at 12:40
-
2\$\begingroup\$ AF_INET and SOCK_STREAM are just constants; AF_INET is 2 and SOCK_STREAM is 1. Also, as mentioned, SOCK_STREAM is unnecessary; so you can shorten that by instead using
s=socket(2)
. \$\endgroup\$Skyler– Skyler2016年03月28日 17:49:46 +00:00Commented Mar 28, 2016 at 17:49 -
1\$\begingroup\$ can't you just do socket() and therefore save another byte? \$\endgroup\$Foon– Foon2016年03月28日 18:42:25 +00:00Commented Mar 28, 2016 at 18:42
-
1\$\begingroup\$ You can save 10 characters by using Python 2. Then,
int(input())
becomesinput()
and the send part becomesc.send(`eval(a[0].replace(".","+"))`)
\$\endgroup\$Blender– Blender2016年03月29日 23:40:04 +00:00Commented Mar 29, 2016 at 23:40
Java, (削除) 371 (削除ここまで) (削除) 368 (削除ここまで) (削除) 350 (削除ここまで) (削除) 344 (削除ここまで) (削除) 333 (削除ここまで) (削除) 310 (削除ここまで) (削除) 295 (削除ここまで) 282 bytes
Golfed
import java.net.*;class A{public static void main(String[]n)throws Exception{ServerSocket s=new ServerSocket(Integer.decode(n[0]));for(;;){try(Socket a=s.accept()){byte[]c=a.getInetAddress().getAddress();new java.io.PrintStream(a.getOutputStream()).println(c[0]+c[1]+c[2]+c[3]);}}}}
Ungolfed
import java.net.*;
class A {
public static void main(String[] n) throws Exception {
ServerSocket s = new ServerSocket(Integer.decode(n[0]));
for (;;) {
try (Socket a = s.accept()) {
byte[] c = a.getInetAddress().getAddress();
new java.io.PrintStream(a.getOutputStream()).println(c[0] + c[1] + c[2] + c[3]);
}
}
}
}
Output
mallard@steamroller:~$ telnet localhost 8888
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
128
Connection closed by foreign host.
-
1\$\begingroup\$ Remove the
int k=
and replace the k with all the c things inInteger.toString(k)
. To save a few bytes. \$\endgroup\$GiantTree– GiantTree2016年03月28日 13:40:43 +00:00Commented Mar 28, 2016 at 13:40 -
1\$\begingroup\$ Javas byte pretty sure messes up the return value for 192.168.2.1 or similar adresses with a byte above 127. \$\endgroup\$AlexR– AlexR2016年03月28日 17:06:57 +00:00Commented Mar 28, 2016 at 17:06
-
1\$\begingroup\$ Change
interface
toclass
should gain few more byte \$\endgroup\$ortis– ortis2016年03月29日 08:37:51 +00:00Commented Mar 29, 2016 at 8:37 -
2\$\begingroup\$ Use
a.getOutputStream().write((c[0] + c[1] + c[2] + c[3]+"\n").getBytes());
instead ofnew DataOutputStream(a.getOutputStream()).writeBytes(c[0] + c[1] + c[2] + c[3] + "\n")
\$\endgroup\$ortis– ortis2016年03月29日 09:17:58 +00:00Commented Mar 29, 2016 at 9:17 -
3\$\begingroup\$ Isn't
try(Socket a=...){}
shorter thana.close();
? Requires Java 7, but can gain bytes. \$\endgroup\$Olivier Grégoire– Olivier Grégoire2016年03月29日 14:53:23 +00:00Commented Mar 29, 2016 at 14:53
PowerShell v2+, (削除) 303 (削除ここまで) (削除) 268 (削除ここまで) (削除) 257 (削除ここまで) 227 bytes
nal n new-object;($l=n Net.Sockets.TcpListener($args[0])).Start()
for(){($w=n IO.StreamWriter(($c=$l.AcceptTcpClient()).GetStream())).Write((([Net.IPEndPoint]$c.Client.RemoteEndPoint).Address-replace"\.",'+'|iex))
$w.Dispose()}
Saved 35 bytes thanks to Matt ... Saved another 11 bytes by aliasing New-Object
and minor tweaks ... Saved 30 more bytes by implicitly using localhost rather than any
IP address and corrected to account for continual usage as originally specified and I missed
Really similar to the C# answer, since it's .NET underlying both. We save a few bytes here over the C# answer by being able to leverage the returning functionality of PowerShell (surrounding our declaration/assignment in parens, and then immediately calling the . methods), but we lose an awful lot by needing to formulate the summation. The fact that we've got slightly shorter class names/calls is really why this answer is beating C#.
Explanation
We first create a New-Alias
(with the nal
alias) to save on re-typing New-Object
later. The rest of the first line is setting up a TCP Listener. We pass the command-line $args[0]
as the input for creating a new System.Net.Sockets.TcpListener
, stored as $l
. That object is encapsulated in parens and immediately called with .Start()
to have it actively open the socket.
Entering an infinite for
loop, we then set our listener $l
to blocking with AcceptTcpClient()
which will wait for a connection. A reference to that connection (once it's made) is stored in $c
, encapsulated in parens, and immediately called GetStream()
to get the datastream. That datastream is passed to a new System.IO.StreamWriter
constructor, $w
, so we can manipulate it. That constructor is itself encapsulated in parens and immediately called Write(...)
.
Inside the Write(...)
call, we take our client handle $c
and obtain the client's RemoteEndPoint
property. This is the only way (that I've found so far) to get the remote IP address. Next we need to re-cast that as a [System.Net.IPEndPoint]
object so it's formatted correctly, encapsulate that in parens, and pull just the .Address
property. We then -replace
the literal periods with plus signs, then pipe it to Invoke-Expression
(similar to eval
) to obtain our summation.
After the IO write, we need to call .Dispose()
to ensure the datastream is flushed to the client and closed. The TCP server drops the client connection without warning, so depending upon the client used it may hang for a while at this point. It then continues through the for
loop without properly closing connections. This also means that it leaks memory and system handles like crazy, but we don't care about that, right? You may need to use Task Manager to kill the process when you're done running the server, though. :D
Also IPv4 only, as the summation barfs spectacularly trying to handle an IPv6 address, since :
isn't a valid algebraic operator for iex
to parse.
-
2\$\begingroup\$ "Leaks memory and system handles like crazy" What, do you have to
free()
them after?delete[]
, maybe? :P \$\endgroup\$cat– cat2016年03月28日 15:25:06 +00:00Commented Mar 28, 2016 at 15:25 -
8\$\begingroup\$ @tac Yeah, there's a whole slew of
.close()
and.dispose()
methods we're not calling here that would cause people on Code Review to have a fit. \$\endgroup\$AdmBorkBork– AdmBorkBork2016年03月28日 15:27:50 +00:00Commented Mar 28, 2016 at 15:27 -
\$\begingroup\$ Oh, isn't PS GC'd? Or does the GC do refcounting and not scope-analysis? \$\endgroup\$cat– cat2016年03月28日 15:28:42 +00:00Commented Mar 28, 2016 at 15:28
-
\$\begingroup\$ @tac Yes, PowerShell does have garbage collection thanks to the underlying .NET system. But, depending on how you're calling or leveraging this script, you can run into bugs like this one leaking memory in the pipeline. The above code also isn't thread-safe, and so can run into GC issues with that, since we're not explicitly closing the socket. \$\endgroup\$AdmBorkBork– AdmBorkBork2016年03月28日 15:40:10 +00:00Commented Mar 28, 2016 at 15:40
-
1\$\begingroup\$ In testing I could not get this to work, likely due to firewall issues that I don't feel like fixing so I cannot be sure but..... I think you can drop "System" from most if not all the type casts you have there ie:
[Net.ipaddress]::Any
works. \$\endgroup\$Matt– Matt2016年03月28日 16:21:41 +00:00Commented Mar 28, 2016 at 16:21
PHP, 161 (56?)
This is my first post in here. I hope this goes right :)
<?php $s=socket_create_listen($argv[1]);while($c=socket_accept($s)){socket_getpeername($c,$r);socket_write($c,array_sum(explode('.',$r))."\n");socket_close($c);}
Ungolfed:
<?php
$s = socket_create_listen($argv[1]); //Create socket
while( $c = socket_accept($s) ) { // Loop accepting new connections
socket_getpeername($c, $r); // Get IP address in $r
socket_write($c, array_sum(explode('.', $r))."\n"); //Calculate sum
socket_close($c); //Close connection and wait for next one
}
Terminal:
$ php test.php 8080 &
$ telnet localhost 8080
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
128
Connection closed by foreign host.
This only works for IPV4
Edit:
I just noticed that php supports basic server:
I decided stick to original character count unless somebody confirms if following is allowed :)
test2.php: (possible 56-byte solution)
<?=array_sum(explode('.',$_SERVER['REMOTE_ADDR']))."\n";
And then start service with:
php -S localhost:8080 test2.php
Chrome as client screenshot
Edit 2: wget as client
$ wget -qO- localhost:8080
128
-
\$\begingroup\$ I know rules say: "Program or function reads integer N from arguments or stdin", but is it ok if program in this case is php itself? Or is using builtin server in php considered loophole? \$\endgroup\$Mikael– Mikael2016年03月29日 20:36:56 +00:00Commented Mar 29, 2016 at 20:36
-
\$\begingroup\$ Welcome to Programming Puzzles & Code Golf! Your 161-byte solution looks great. Is the 56-byte solution you mentioned the one under
test2.php
? If so, I think you'd have to ask the OP whether they'd consider that kind of built-in acceptable for this challenge. It isn't a loophole though. \$\endgroup\$Alex A.– Alex A.2016年03月30日 05:13:40 +00:00Commented Mar 30, 2016 at 5:13 -
\$\begingroup\$ I would say, using a builtin TCP server would be acceptable, but in this case we talk about a builtin HTTP server. So the 56 byte solution 1) does nothing if the client only connects and sends nothing; 2) sends back only "[Wed Mar 30 10:15:02 2016] 127.0.0.1:47974 Invalid request (Malformed HTTP request)" without running test2.php in case the client sends for example "foo"; 3) sends full set of HTTP response headers before the actual required response in case the client sends valid HTTP request. \$\endgroup\$manatwork– manatwork2016年03月30日 07:19:39 +00:00Commented Mar 30, 2016 at 7:19
-
\$\begingroup\$ @Alex A. Thank you and yes, 56-byte solution is under test2.php :) \$\endgroup\$Mikael– Mikael2016年03月30日 14:48:10 +00:00Commented Mar 30, 2016 at 14:48
-
\$\begingroup\$ @manatwork You are correct but I was thinking that client is not clearly specified in this task. So is it ok to use browser or even more simplier something like "wget -qO- localhost:8080" as client? \$\endgroup\$Mikael– Mikael2016年03月30日 14:48:21 +00:00Commented Mar 30, 2016 at 14:48
Go, (削除) 359 (削除ここまで) 311
This is my first program in Go - It allowed to let me discover one thing : This is definitively not a good golfing language!
(Kudos to @steve who did most of the golfing !)
package main
import(n"net";t"strings";r"strconv";x"regexp";"os")
func main(){l,_:=n.Listen("tcp",":"+os.Args[1])
for{c,_:=l.Accept();var s int
for _,i:=range t.Split(x.MustCompile(":[0-9]+$").ReplaceAllLiteralString(c.RemoteAddr().String(),""),"."){
n,_:=r.Atoi(i);s=s+n};c.Write([]byte(r.Itoa(s)));c.Close()}}
-
2\$\begingroup\$ But it sure is a nice language for making a tcp server! \$\endgroup\$Numeri– Numeri2016年03月29日 20:52:55 +00:00Commented Mar 29, 2016 at 20:52
-
1\$\begingroup\$ Odd, am getting the result 360 when I connect from 192.168.0.67, rather than 427. \$\endgroup\$steve– steve2016年03月29日 21:43:31 +00:00Commented Mar 29, 2016 at 21:43
-
3\$\begingroup\$ You could name the strings+strconv packages to save a few bytes. e.g.
"strings"
becomess "strings"
so that the laterstrings.Split
becomes justs.Split
. \$\endgroup\$steve– steve2016年03月29日 21:49:32 +00:00Commented Mar 29, 2016 at 21:49 -
1\$\begingroup\$ Few more bytes shaved off pastebin.com/HY84sazE - starting to look a bit more "golfed" now \$\endgroup\$steve– steve2016年03月30日 20:32:04 +00:00Commented Mar 30, 2016 at 20:32
-
2\$\begingroup\$ If you use
import(."pkgname")
all functions will be imported to the current namespace, you can then drop the prefix. eg.import ."fmt"; Println("foo")
If you useSscanf
from thefmt
package to parse the address instead of regex it'll save you another few bytes, giving you the nice bonus of havingFprintln
for returning the total instead of importingstrconv
. \$\endgroup\$Kristoffer Sall-Storgaard– Kristoffer Sall-Storgaard2016年03月31日 12:10:07 +00:00Commented Mar 31, 2016 at 12:10
Common Lisp, 110 bytes
(use-package'usocket)(lambda(p)(socket-server"localhost"p(lambda(u)(format u"~D~%"(reduce'+ *remote-host*)))))
Details
(use-package 'usocket)
(lambda (port)
;; create server with event-loop
(socket-server "localhost"
port
;; tcp-handler
(lambda (stream)
;; format to stream to client
(format stream
"~D~%"
;; add all elements of the host,
;; a vector of 4 integers
(reduce #'+ *remote-host*))
;; client connection is closed automatically
;; when exiting this function
)))
-
2\$\begingroup\$ Yay for Common Lithp! \$\endgroup\$cat– cat2016年04月08日 13:43:08 +00:00Commented Apr 8, 2016 at 13:43
q, 88 bytes
system raze"p ",1_.z.x;.z.pg:{(string sum"i"0ドルx0 vs .z.a),"\n"};.z.ph:{.h.hy[`;.z.pg[]]}
system raze"p ",1_.z.x
: Takes the second command-line argument (the first"-"
is for tellingq
not to interpretN
as a script/file) and opens a port ("p "
) with it.- Note: Calling
q -p N
sets the port asN
automatically, but since the question seems to suggest thatN
should be an argument to the program rather than the executable itself, I've gone the longer way.
- Note: Calling
- Inside the
.z.pg
function that handles incoming requests,.z.a
holds the IP address as a 32-bit integer."i"0ドルx0 vs
splits it into its integer 'constituents', andsum
does the summation.- Last,
string
the numeric result and append"\n"
to it to return to the client.
.z.ph
is another function for HTTP GET requests, with extra handling to convert the string output into a valid HTTP response.
Demo - Server:
c:\q\w32>q - 1234
KDB+ 3.3 2015年11月03日 Copyright (C) 1993-2015 Kx Systems
w32/ 4()core ... NONEXPIRE
Welcome to kdb+ 32bit edition
q)system raze"p ",1_.z.x;.z.pg:{(string sum"i"0ドルx0 vs .z.a),"\n"};.z.ph:{.h.hy[`;.z.pg[]]}
q)
Demo - Client (from another q
session running on 127.0.0.1
):
q)(hopen `::1234)""
"128\n"
Demo - Client (from curl
):
$ curl localhost:1234
128
$
8086 machine code (16-bit DOS), (削除) 163 156 148 148 (削除ここまで) 142 bytes
00000000 31 c0 bb 0a 00 31 c9 be 81 00 bf 80 00 8a 0d 01 |1....1..........|
00000010 cf 46 8a 0c 80 e9 30 f7 e3 00 c8 39 fe 72 f2 89 |.F....0....9.r..|
00000020 c3 89 c1 b8 01 10 ba ff ff 31 f6 31 ff cd 61 53 |.........1.1..aS|
00000030 b8 00 12 bf 80 00 b9 01 00 ba ff ff cd 61 b8 00 |.............a..|
00000040 14 cd 61 31 c0 bb 0a 00 83 c7 06 8d 4d 04 26 02 |..a1........M.&.|
00000050 05 80 d4 00 47 39 cf 72 f5 bf 84 00 b9 80 00 bb |....G9.r........|
00000060 0a 00 4f 31 d2 f7 f3 80 c2 30 88 15 39 cf 77 f2 |..O1.....0..9.w.|
00000070 1e 07 b8 0e 13 5b bf 80 00 b9 04 00 ba ff ff cd |.....[..........|
00000080 61 b8 00 11 ba 01 00 cd 61 b8 00 4c cd 21 |a.......a..L.!|
0000008e
Equivalent assembly code:
org 0x100
tcp equ 0x61 ; NTCPDRV interrupt
xor ax,ax
mov bx,10
xor cx,cx
mov si,0x81 ; [ds:81]-[ds:FF] = command line args
mov di,0x80 ; [ds:80] = strlen(args)
mov cl,[di]
add di,cx
@@: inc si
mov cl,[si] ; get character
sub cl,'0' ; convert char to int
mul bx ; ax *= 10
add al,cl
cmp si,di
jb @b
; now ax = port number
mov bx,ax ; source port (leaving this 0 doesn't work?)
mov cx,ax ; dest port
mov ax,0x1001 ; open TCP socket for listening
mov dx,-1 ; infinite timeout
xor si,si ; any dest IP
xor di,di
int tcp
; ^ I think this call should block until a connection is established, but apparently it doesn't.
push bx ; bx = socket handle, save it for later
mov ax,0x1200 ; read from socket
mov di,0x80 ; es:di = buffer (just reuse argument area to save space)
mov cx,1 ; one byte
mov dx,-1
int tcp ; this will block until a client connects and sends one byte
mov ax,0x1400 ; get TCP session status, bx=handle
int tcp
; now es:di points to a struct containing the source/dest IP addresses and ports
; the docs say it's two dwords for each IP address, then two bytes for "ip_prot" and "active" (whatever that means)
; ...but actually each IP address is followed by the port number (one word)
xor ax,ax
mov bx,10
add di,6 ; [es:di+6] = client IP
lea cx,[di+4]
@@: add al,[es:di] ; add all bytes together
adc ah,0
inc di
cmp di,cx
jb @b
; now ax contains the IP address sum
mov di,0x84 ; recycle arguments area again
mov cx,0x80
mov bx,10
@@: dec di
xor dx,dx
div bx ; dl = ax mod 10
add dl,'0' ; convert int to char
mov [di],dl
cmp di,cx
ja @b
; now [ds:80]-[ds:83] contains an ascii representation of the IP address sum
push ds
pop es
mov ax,0x130e ; send data with newline, wait for ack
pop bx ; socket handle
mov di,0x80 ; es:di = data
mov cx,4 ; sizeof data
mov dx,-1
int tcp
mov ax,0x1100 ; close TCP socket
mov dx,1
int tcp
mov ax,0x4c00
int 0x21
This assumes ntcpdrv
is loaded at INT 0x61
(and any suitable packet driver at 0x60
). Compile with fasm tcpserv.asm
.
It has some issues though:
- It doesn't check if the argument is a valid port number, or if it's even a number at all.
- The client must send at least one byte, since I can't seem to find any other way to tell if a client has connected.
- It only works once, and hangs on a second attempt. Works again after a reboot.
- The returned value is left-padded with zeroes.
- This is my very first code golf entry, and also my very first 8086 asm program. I'm sure there are ways to improve this further.
-
1\$\begingroup\$ You can just post a hexdump of the compiled output for 148 bytes \$\endgroup\$cat– cat2016年04月08日 13:37:07 +00:00Commented Apr 8, 2016 at 13:37
-
1\$\begingroup\$ Alright, I've changed the entry to machine code. Also shaved a few more bytes off by using
xor r,r
instead ofmov r,0
. \$\endgroup\$user5434231– user54342312016年04月08日 20:17:13 +00:00Commented Apr 8, 2016 at 20:17 -
1\$\begingroup\$ I wrote it on a dos machine where newlines are
CR LF
, so I just went with that. Either way it's kinda pointless to count the asm size now, might as well clean it up a bit and add some comments. \$\endgroup\$user5434231– user54342312016年04月09日 15:54:10 +00:00Commented Apr 9, 2016 at 15:54 -
1\$\begingroup\$
source port (leaving this 0 doesn't work?)
On UNIX, giving a port of0
lets the kernel randomly assign a port, then returns the new port number. I guess DOS doesn't have that functionality \$\endgroup\$cat– cat2016年04月09日 16:24:24 +00:00Commented Apr 9, 2016 at 16:24 -
2\$\begingroup\$ That's supposed to happen here too, and it does work;
int 0x61
returns a random local port inax
. But it also changes the listening IP to some garbage number (4.2.0.0
iirc) \$\endgroup\$user5434231– user54342312016年04月09日 16:39:17 +00:00Commented Apr 9, 2016 at 16:39
LiveScript, (削除) 107 (削除ここまで) 105 bytes
(require \http)createServer(->&1.end((.reduce (+))<|it.connection.remoteAddress/\.))listen process.argv.0
Nothing much to add, it's just basic NodeJS stuff. Style points for &1
(second argument), <|
(F# piping, akin to $
in Haskell) and biop: (+)
in LS is like operator sections in Haskell: a curried binary function (that adds its operands).
Also a bit dirty: /
, if given a literal string on its right, will do split.
Perl, (削除) 141 (削除ここまで) 132 + 1 = 133 bytes
Golfed
$s=new IO::Socket::INET LocalPort=><>,Listen=>5,Reuse=>1;{$c=$s->accept;$_=$c->peerhost;y/./+/;$c->send(eval.$/);shutdown $c,1;redo}
Ungolfed
# listen on tcp port obtained from stdin
$s=new IO::Socket::INET(LocalPort=> <>,
Listen => 5,
Reuse => 1);
{
# accept connection
$c=$s->accept();
# get the ip address
$_=$c->peerhost();
# replace dots with plus
y/./+/;
# send the evaluated version back, with a newline
$c->send(eval . $/);
# close
shutdown($c,1);
redo;
}
Example
$ echo 7777|perl -MIO::Socket::INET -e'$s=new IO::Socket::INET LocalPort=><>,Listen=>5,Reuse=>1;{$c=$s->accept;$_=$c->peerhost;y/./+/;$c->send(eval.$/);shutdown $c,1;redo}'
$ telnet 127.0.0.1 7777
Trying 127.0.0.1...
Connected to 127.0.0.1.
Escape character is '^]'.
128
Connection closed by foreign host.
$
-
\$\begingroup\$ Are you sure this is correct? I get the sum printed in the server's terminal, not the client's. Anyway, you can remove all parenthesis and change
s/\./+/g
→y/./+/
. \$\endgroup\$manatwork– manatwork2016年03月28日 18:08:22 +00:00Commented Mar 28, 2016 at 18:08 -
\$\begingroup\$ Ahh, misread..will revise accordingly and incorporate your good y/ suggestion. \$\endgroup\$steve– steve2016年03月28日 18:22:59 +00:00Commented Mar 28, 2016 at 18:22
-
1\$\begingroup\$
while(1){...}
→{...;redo}
according to user130144's great tip. And excepting the->send()
call, all other parenthesis are unnecessary. \$\endgroup\$manatwork– manatwork2016年03月29日 12:36:35 +00:00Commented Mar 29, 2016 at 12:36
Python 2, 180 bytes
from SocketServer import*
TCPServer(('',input()),type('',(BaseRequestHandler,set),{'handle':lambda s:s.request.send(`eval(s.client_address[0].replace('.','+'))`)})).serve_forever()
Takes the port over stdin.
NodeJS (ES6), (削除) 129 (削除ここまで) (削除) 118 (削除ここまで) 107 bytes
require('net').createServer(c=>c.end(eval(c.remoteAddress.replace(/\./g,'+'))+`
`)).listen(process.argv[2])
Works for IPv4. Run as node server.js <port>
-
\$\begingroup\$ Actually doesn't work if the server's using IPv6 (as, for instance, mine does automatically), since
c.remoteAddress
would then be::ffff:127.0.0.1
. (I tested on Node v5.9.1). \$\endgroup\$Freyja– Freyja2016年03月29日 23:36:35 +00:00Commented Mar 29, 2016 at 23:36 -
\$\begingroup\$ Also, you don't have a trailing newline, which should increase your score by 2 bytes. \$\endgroup\$Freyja– Freyja2016年03月29日 23:40:04 +00:00Commented Mar 29, 2016 at 23:40
-
\$\begingroup\$ @Frxstrem Whoops, forgot that newline. Only adds 1 byte though thanks to template strings. Regarding IP family:
.listen()
used to default to IPv4 first, but it seems either by bug or design that this has changed. The submission will still function properly on newer versions of node when IPv6 is disabled on the host machine. \$\endgroup\$Mwr247– Mwr2472016年03月30日 00:05:06 +00:00Commented Mar 30, 2016 at 0:05
Go, 211 bytes
package main
import(."fmt"
."net"
"os")
func main(){s,_:=Listen("tcp4",":"+os.Args[1])
for{c,_:=s.Accept()
var a,b,d,e int
Sscanf(Sprint(c.RemoteAddr()),"%d.%d.%d.%d",&a,&b,&d,&e)
Fprintln(c,a+b+d+e)
c.Close()}}
Can probably be golfed further, I'm not entirely satisfied with the way I have to parse the IP adress for instance, it looks like a horrible hack.
Listens on IPv4 on the port given as argument.
PowerShell, (削除) 208 (削除ここまで) (削除) 206 (削除ここまで) (削除) 192 (削除ここまで) 152 bytes
($t=[net.sockets.tcplistener]$args[0]).start();for(){($z=$t.acceptsocket()).send([char[]]"$($z.remoteendpoint.address-replace"\.","+"|iex)");$z.close()}
version information:
Name Value
---- -----
PSVersion 4.0
WSManStackVersion 3.0
SerializationVersion 1.1.0.1
CLRVersion 4.0.30319.34209
BuildVersion 6.3.9600.17400
PSCompatibleVersions {1.0, 2.0, 3.0, 4.0}
PSRemotingProtocolVersion 2.2
Thanks to TimmyD for saving me 14 bytes!
Massive thanks to TessellatingHeckler for saving me 40 bytes
-
\$\begingroup\$ @TimmyD ah oops I missed that that was necessary... fixed now \$\endgroup\$Nacht– Nacht2016年03月30日 21:27:07 +00:00Commented Mar 30, 2016 at 21:27
-
\$\begingroup\$ One of the ways programs are allowed to take input is from stdin. i suppose this particular question doesn't specify that as allowed but it's a general code-golf thing that i think should count for PowerShell. It's unfortunately different from bash in that it doesn't wait for input on stdin if none has been provided. \$\endgroup\$Nacht– Nacht2016年03月31日 12:27:51 +00:00Commented Mar 31, 2016 at 12:27
-
\$\begingroup\$ fair enough. fixed again \$\endgroup\$Nacht– Nacht2016年03月31日 13:29:20 +00:00Commented Mar 31, 2016 at 13:29
-
\$\begingroup\$ Alrighty, now for some golfs -- try the following at 192 --
($t=new-object net.sockets.tcplistener($args[0])).start();for(){($z=$t.acceptsocket()).send(($x=[byte[]][char[]](""+($z.remoteendpoint.address-replace"\.","+"|iex))+32),$x.count,0);$z.close()}
\$\endgroup\$AdmBorkBork– AdmBorkBork2016年03月31日 13:46:30 +00:00Commented Mar 31, 2016 at 13:46 -
1\$\begingroup\$ I think you can knock this down to 152 - drop new-object and cast directly, skip the byte array conversion and do a string cast differently, don't store $x at all and drop the remaining parameters to send(), and it becomes
($t=[net.sockets.tcplistener]$args[0]).start();for(){($z=$t.acceptsocket()).send([char[]]"$($z.remoteendpoint.address-replace"\.","+"|iex)");$z.close()}
- which I've only tested quickly with netcat connecting, but it seems to work the same - connecting from localhost anyway. \$\endgroup\$TessellatingHeckler– TessellatingHeckler2016年04月08日 00:06:17 +00:00Commented Apr 8, 2016 at 0:06
C, 535 bytes
Well, someone had to do this.
I added a single line break so the posted code actually has 536 characters.
#include <stdio.h>
#include <netdb.h>
#include <netinet/in.h>
#include <string.h>
int main(int c,char**v){int f,l;char b[99];struct sockaddr_in d,e;f=socket(AF_INET,SOCK_STREAM,0);bzero(&d,sizeof(d));d.sin_family=AF_INET;d.sin_addr.s_addr=INADDR_ANY;d.sin_port=htons(atoi(v[1]));bind(f,&d, sizeof(d));listen(f,5);l=sizeof(e);
f=accept(f,&e,&l);bzero(b,99);int p,q,r,s;char g[INET_ADDRSTRLEN];inet_ntop(AF_INET,&(e.sin_addr),g,INET_ADDRSTRLEN);sscanf(g,"%d.%d.%d.%d",&p,&q,&r,&s);sprintf(b,"%d\n",p+q+r+s);write(f,b,strlen(b));return 0;}
compile with gcc [file_name] -o server
run with ./server [port]
connect with telnet localhost [port]
-
3\$\begingroup\$ Nice answer! As mentioned before, you could save a few bytes by using actual values for some constants, such as AF_INET and SOCK_STREAM. \$\endgroup\$Hannes Karppila– Hannes Karppila2016年04月01日 10:15:34 +00:00Commented Apr 1, 2016 at 10:15
Haskell, 216 bytes
Using the "network-simple" package (cabal install network-simple
). Needs a couple of language extensions (-XOverloadedStrings -XNoMonomorphismRestriction
) to work.
import Network.Simple.TCP(serve)
import Network.Socket
import Data.Bits
main=getLine>>= \n->serve"*"n p
p(s,(SockAddrInet _ h))=()<$(send s$(show$sum$w h 24)++"\n")
m=255
w h 0=[h.&.m]
w h n=h`shiftR`n.&.m:(w h$n-8)
There are a couple of possible simplifications, including changing the w
function to return the sum directly rather than a list, and using a function rather than a program so that the port number can be specified as an argument. I don't imagine this would reduce the size very much, though. 20 bytes perhaps?
-
\$\begingroup\$ Nice! Pretty sure you can still shave a few bytes off by renaming
w
to#
, sow h n
becomesh#n
for a savings of 2 bytes per usage. \$\endgroup\$fmt– fmt2016年04月06日 00:10:27 +00:00Commented Apr 6, 2016 at 0:10
Mumps, (削除) 114 (削除ここまで) 115 Bytes
Golfed:
R P F{S J=0,I="|TCP|1" O I:(:P) U I R K F K=1:1:4{S J=J+$P(##class(%SYSTEM.TCPDevice).PeerAddr(),".",K)} W J,! C I}
Ungolfed:
R P ; Read Port # from STDIN ;
F{ ; Loop over everything;
S J=0, ; Initial IP segment total
I="|TCP|1" ; TCP device
O I:(:P) ; Open the TCP device, port from input {and sticking a tongue out! :-) }
U I ; Use the TCP device
R K ; Read from STDIN (anything)
F K=1:1:4{ ; Iterate 1->4 in variable K
S J=J+ ; Accumulate the following segments of the IP in var. J
$P(##class(%SYSTEM.TCPDevice).PeerAddr(),".",K) ; Grab each piece of IPv4.
} ; close the loop.
W J,! ; Write the total w/newline out the TCP port
C I ; close the TCP port to send.
} ; end final loop
This is the InterSystems Caché version of Mumps - if there's a version out there that can acquire the TCP address shorter than ##class(%SYSTEM.TCPDevice).PeerAddr()
(as it's almost a 1/3 of the entire program) it might have a better chance against some of the other languages posted already... ;-)
Edit: Thanks to @TimmyD - I missed the reading of the port from STDIN or arguments instead of being hardcoded. Edited; it added 1 byte to the program.
-
\$\begingroup\$ @TimmyD - Ah, you're correct. Missed that on reading through the requirements. Will edit posthaste. \$\endgroup\$zmerch– zmerch2016年04月04日 21:43:01 +00:00Commented Apr 4, 2016 at 21:43
C, (削除) 243 (削除ここまで) 188 bytes (or perhaps (削除) 217 (削除ここまで) 162 bytes)
V2: see below for the explanations.
188 bytes:
s;main(g,v)char**v;{short S[8]={2,htons(atoi(v[1]))};char C[g=16];bind(s=socket(2,1,0),&S,g);for(listen(s,8);g=fdopen(accept(s,&C,&g),"w");fclose(g))fprintf(g,"%d\n",C[4]+C[5]+C[6]+C[7]);}
Slightly circumspect 162 bytes:
s;main(g){short S[8]={2,g};char C[g=16];bind(s=socket(2,1,0),&S,g);for(listen(s,8);g=fdopen(accept(s,&C,&g),"w");fclose(g))fprintf(g,"%d\n",C[4]+C[5]+C[6]+C[7]);}
Probably more golfing possible tomorrow morning. I'll tidy this post up after those updates.
V1:
This one was really quite fun to golf.
#include<netdb.h>
s,c,q;main(g,v)char**v;{struct sockaddr_in S={2,htons(atoi(v[1]))},C;bind(s=socket(2,1,0),&S,g=16);for(listen(s,8);c=accept(s,&C,&g);q=fclose(g)){for(g=4;g;q+=C.sin_addr.s_addr>>8*--g&255);fprintf(g=fdopen(c,"w"),"%d\n",q);}}
It works for IPv4. Mostly it's a straightforward implementation. The three main components are
Creating the socket:
struct sockaddr_in S={2,htons(atoi(v[1]))},C;bind(s=socket(2,1,0),&S,g=16);
We use the various explicit forms of the constants AF_INET etc, and make use of the fact that when a struct is initialised in C in this way the non-specified elements are set to zero.
Listen for clients, accept them, and close their connections:
for(listen(s,8);c=accept(s,&C,&g);q=fclose(g))
Finally to send each client the data:
for(g=4;g;q+=C.sin_addr.s_addr>>8*--g&255);fprintf(g=fdopen(c,"w"),"%d\n",q);
The IP is stored in C.sin_addr.s_addr
as a 32 bit integer where each octet is represented by one of the four bytes. We sum these bytes with the for loop and then print them to the stream using fprintf.
I have a shorter 217 byte solution but I'm not entirely sure it doesn't violate the standard loopholes since it requires that the port is given in unary in network byte order as command line arguments. That is, to run the server on port 12345 one would need to call
$ ./tcp 1 1 1 1 ... 1 1 1
where the total number of 1
s is 14640. To say the least it's a little... cumbersome. But here it is anyway:
#include<netdb.h>
s,c,q;main(g){struct sockaddr_in S={2,g},C;bind(s=socket(2,1,0),&S,g=16);for(listen(s,8);c=accept(s,&C,&g);q=fclose(g)){for(g=4;g;q+=C.sin_addr.s_addr>>8*--g&255);fprintf(g=fdopen(c,"w"),"%d\n",q);}}
Java, 210 bytes
Golfed:
p->{java.net.ServerSocket x=new java.net.ServerSocket(p);for(;;){try(java.net.Socket s=x.accept()){byte[]b=s.getInetAddress().getAddress();s.getOutputStream().write((0+b[0]+b[1]+b[2]+b[3]+"\n").getBytes());}}};
Expanded:
@FunctionalInterface interface Consumer { // Define an interface that allows a function that throws an exception.
void accept(int port) throws Exception;
}
Consumer consumer = (port) -> {
java.net.ServerSocket serverSocket = new java.net.ServerSocket(port);
for (;;) {
try (java.net.Socket socket = serverSocket.accept()) {
byte[] bytes = socket.getInetAddress().getAddress();
socket.getOutputStream().write((0 + b[0] + b[1] + b[2] + b[3] + "\n").getBytes());
}
}
}
This a gathering of all the tips I gave in other Java answers, plus the writing as a function instead of a full program, which gains roughly 70 bytes compared to the program.
Haskell, 326 bytes
import Data.Bits
import Network.Socket
import System.IO
f n=withSocketsDo$do
s<-socket AF_INET Stream defaultProtocol
bind s$SockAddrInet n iNADDR_ANY
listen s 1
g s
g s=do
(z,SockAddrInet _ a)<-accept s
h<-socketToHandle z WriteMode
hPutStrLn h$show$b a
hClose h
g s
b 0=0
b x=x.&.0xFF+b(x`shiftR`8)
Sadly I had to use Network.Socket
to get access to the remote IP address as an integer rather than a string. It would have saved dozens of characters if I could just do s <- listenOn (PortNumber n)
, rather than having to explicitly call socket
, bind
and listen
individually. But, sadly, Network.accept
gives me a host string, not an IP address integer, so I had to resort to Network.Socket.accept
and friends.
The function f
takes a port number as argument, and creates a server socket (s
) listening on that port. It then calls the function g
with the server socket. g
loops forever, accepting connections. The function b
takes an actual IPv4 address and computes the sum of its digits.
I'm sure somebody somewhere can do this better than me. I wanted to show off just how damned easy socket stuff is in Haskell... but then failed miserably, because I need access to the IP address, which isn't usually easy to get.
-
\$\begingroup\$ The "network-simple" package provides a much nicer interface which passes the SockAddr to a function you give it, which makes things easier. See my solution which I'm about to post... \$\endgroup\$Jules– Jules2016年03月31日 15:49:19 +00:00Commented Mar 31, 2016 at 15:49
-
\$\begingroup\$ A few simplifications are apparent: (1) I believe
withSocketsDo
is only necessary on Windows, so if running on Linux it can be ignored; (2) 0xFF is a character longer than 255; (3) converting the socket to a handle and using regular IO is a lot longer than usingNetwork.Socket.send
. Yes,send
is deprecated, but the reason is not relevant to this scenario (it only relates to non-ASCII text or binary data), so it seems reasonable to use it. \$\endgroup\$Jules– Jules2016年03月31日 16:04:13 +00:00Commented Mar 31, 2016 at 16:04 -
\$\begingroup\$
Network.accept gives me a host string, not an IP address integer
Can't you just split the IP string on the"."
,map
Haskell's string-to-number function over the split string and sum the results? \$\endgroup\$cat– cat2016年05月02日 02:21:52 +00:00Commented May 2, 2016 at 2:21
Lua, (削除) 169 (削除ここまで) (削除) 162 (削除ここまで) (削除) 160 (削除ここまで) (削除) 153 (削除ここまで) (削除) 151 (削除ここまで) (削除) 148 (削除ここまで) (削除) 138 (削除ここまで) 129 bytes
Golfed version
m=require"socket".bind(0,...)::l::c=m:accept()f=0 for n in c:getpeername():gmatch"%d+"do f=f+n end c:send(f.."\n")c:close()goto l
It requires Luasocket to be installed and an interpreter that supports labels. I've tested it with Luajit and I can also confirm that the code does not work with Lua 5.1.
Ungolfed version
m=require"socket".bind(0,...)
::l::
c=m:accept()
f=0
for n in c:getpeername():gmatch"%d+" do
f=f+n
end
c:send(f.."\n")
c:close()
goto l
Edit 1:
Changed i=({c:getpeername()})[1]
to just i=c:getpeername()
Edit 2:
Removed braces from the require statement.
Edit 3:
Removed the braces around the vararg, decreased the byte count a little bit.
Edit 4:
Removed the parenthesis around "%d+", shorter by 2 bytes.
Edit 5:
Removed the unnecessary variable i.
Edit 6:
Changed the ip from "127.0.0.1" to 0. (Thanks to xyzzy on #lua)
Edit 7:
Removed the function call to tonumber since strings are cast to numbers automatically (Thanks to Trebuchette for the suggestion, I did not know this)
-
1\$\begingroup\$ Only Lua 5.2 and up support labels, if you're curious \$\endgroup\$Trebuchette– Trebuchette2016年03月31日 03:25:50 +00:00Commented Mar 31, 2016 at 3:25
-
1\$\begingroup\$ Also, Lua automatically casts strings to numbers with the
+
operator, so you can take outtonumber
. \$\endgroup\$Trebuchette– Trebuchette2016年03月31日 03:32:11 +00:00Commented Mar 31, 2016 at 3:32
Haskell, 185 (+ 19 = 204)? bytes
import Network.Simple.TCP(serve)
import Network.Socket
import Data.List.Split
main=getLine>>=flip(serve"*4")(\(a,b)->()<$(send a$(++"\n")$show$sum.map read.take 4.sepByOneOf":."$show b)
Takes port number as one line on stdin; requires network-simple
from Cabal.
As usual with Haskell answers that don't constrain themselves to pure functions, the imports
take up far too many bytes. The trailing newline is also worth 9 bytes...
Somewhat similar to @Jules's answer, but I use string manipulation instead of byte operations. I (削除) stole (削除ここまで) used the -XOverloadedStrings
extension as well, which is probably worth 19 bytes extra.
Racket, 265 bytes
#lang racket(define l(tcp-listen(string->number(read-line))))(let e()(define-values(i o)(tcp-accept l))(thread(λ()(define-values(a b)(tcp-addresses o))(write(~a(foldl + 0(map string->number(string-split a".")))o))(newline o)(close-output-port o)))(e)))
Ungolfed:
#lang racket
(define listener (tcp-listen (string->number (read-line))))
(define (mk-server)
(let echo-server ()
(define-values (in out) (tcp-accept listener))
(thread
(λ()
(define-values (a b) (tcp-addresses out))
(write (number->string (foldl + 0(map string->number(string-split a "."))) out))
(write "\n" out)
(close-output-port out)))
(echo-server)))
Factor, (削除) 155 (削除ここまで) (削除) 146 (削除ここまで) (削除) 131 (削除ここまで) (削除) 206 (削除ここまで) 190 bytes
Well, I just learned a lot about low-level socket programming. I don't think I ever wanna do that again, because my (削除) thr (削除ここまで)head hurts.
[ utf8 <threaded-server> readln 10 base> >>insecure [ remote-address get host>> "." split [ 10 base> ] map sum 10 >base print flush ] >>handler [ start-server ] in-thread start-server drop ]
Oh yeah, threaded, and doesn't return, right.
-
\$\begingroup\$ Can you use
10 base>
instead ofstring>number
? \$\endgroup\$fede s.– fede s.2016年04月09日 18:24:59 +00:00Commented Apr 9, 2016 at 18:24 -
\$\begingroup\$ @fedes. Wow, I never knew that existed. I think that will allow me to shorten a lot of my Factor answers! \$\endgroup\$cat– cat2016年04月09日 18:30:12 +00:00Commented Apr 9, 2016 at 18:30
-
\$\begingroup\$ And
10 >base
for number>string, also. \$\endgroup\$fede s.– fede s.2016年04月09日 18:30:58 +00:00Commented Apr 9, 2016 at 18:30 -
1