Un semplice server TCP


104

Scrivi un programma o una funzione che ascolta il traffico TCP in entrata sulla porta N. Offre un servizio semplice: calcola la somma dei campi dell'indirizzo IP della connessione in entrata e restituisce.

Il programma o la funzione legge l'intero N dagli argomenti o dallo stdin. Ascolta le connessioni TCP in entrata sulla porta N. Quando qualcuno si connette a quella porta, il programma calcola la somma dei suoi campi dell'indirizzo IP e lo rimanda al client con una nuova riga finale e chiude la connessione.

  • Il numero di porta N è una porta valida e 2 10 <N <2 15
  • Newline finale può essere \no\r\n
  • È possibile utilizzare IPv4 o IPv6. Poiché gli indirizzi IPv6 sono scritti in forma esadecimale, è necessario fornire anche i risultati nello stesso formato, ad esempio 2001:0db8:0000:0042:0000:8a2e:0370:7334 => 12ecd.

Questo è . Si applicano regole standard e scappatoie.

Esempio

Gestisci il tuo server con ./server 1234. Il server è ora in esecuzione e in attesa di connessioni sulla porta 1234. Quindi un client si 127.0.0.1connette al server. Il server esegue un calcolo semplice: 127+0+0+1 => 128e invia il risultato al client (con trailing nuova riga): 128\n. Quindi il server chiude la connessione e attende il client successivo.

Classifica

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
È consentito utilizzare inetd / xinetd o simili?
Trauma digitale

91
Mi piace questo, dal momento che è una sfida golfistica in cui è improbabile che le lingue golfistiche siano molto brave.
Isaacg,

9
Non solo è sorprendente il fatto che un server TCP sia apparentemente un programma molto semplice da scrivere, ma sono profondamente motivato dal fatto che si sta giocando a golf per divertimento. Tornerò alle lotte con FizzBuzz come un imbecille.
MonkeyZeus,

17
@isaacg È tempo solo prima che qualcuno trovi il server TCP integrato in Mathematica
Downgoat,

3
@MonkeyZeus Per essere onesti, non vedrai nessun buon server TCP qui. Realizzare un server TCP affidabile e scalabile che gestisca bene tutte le complessità di TCP (e del protocollo dell'applicazione) è un po 'più difficile: D Anche se sicuramente aiuta il protocollo ad essere estremamente semplice - non è nemmeno necessario leggere lo stream, qualcosa che ho visto
irrompere

Risposte:


57

Bash + netcat + ss +…, 65 60 caratteri

nc -lp$1 -c'ss src :'$1'|awk \$0=\$5|tr .: +#|bc'
exec $0 $1

Non era una soluzione seria, era solo curioso di questa possibilità.

Grazie a:

  • ninjalj per aver suggerito il awkfiltro basato (-5 caratteri)

Esecuzione di esempio:

(Terminale 1)

bash-4.3$ ./ip-reduce.sh 8080

(terminale 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.

Su Ubuntu puoi ottenere ncda netcat-tradizionale (no, netcat-openbsd non è buono) e ssda iproute2 .


22
Perché dici che non è una soluzione seria? Finché funziona come previsto, non vedo alcun motivo per cui non dovrebbe essere considerato serio. È anche il più corto con un margine abbastanza significativo al momento.
Alex A.

La più grande preoccupazione nei suoi confronti è emersa durante la discussione con @JesseSielaff quando ho appreso che sui sistemi con IPv6 configurato, le informazioni relative al socket potrebbero essere formattate diversamente. Non hanno tale sistema per testarlo. Per cui sto pensando se sarebbe più corretto trasformarlo in CW.
arte

3
La mia comprensione delle specifiche è che devi supportare IPv4 o IPv6, non entrambi. Quindi, fintanto che funziona per IPv4, non supportare IPv6 non dovrebbe importare, penso.
Alex A.

1
@AlexA. Almeno penso che la mia domanda lo dica. Dovrei chiarirlo?
Hannes Karppila,

@HannesKarppila, la tua domanda è chiara. Il possibile problema è che la mia soluzione potrebbe richiedere che il sistema operativo sia configurato in un modo particolare per poter funzionare. Quindi sono preoccupato perché potrebbe non riuscire se IPv6 è configurato, indipendentemente dal fatto che lo gestisca o meno. Qualcuno che ha configurato IPv6 potrebbe dirlo con certezza ...
Manatwork

23

C #, 284 283 282 278 274 254 byte

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]);}}}

Esempio classico di un server TCP C # di base. test:

Terminale 1:

$ ./Q76379.exe 1029

Terminale 2:

$ telnet localhost 1029
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
128
Connection closed by foreign host.

Firefox:


7
È possibile salvare 1 byte utilizzando int Maininvece di void Main. Poiché il programma non restituisce mai, il compilatore non richiede returnun'istruzione.
raznagul,

E no, non perde. In realtà è piuttosto deterministico riguardo al rilascio di risorse. Inoltre, l'argomento su Startè facoltativo, salvando un altro personaggio.
Luaan,

@Luaan Sì, questo è stato lasciato dal debug.
LegionMammal978,

Inoltre, potresti usare usingsul TcpClient, che ti salverà altri tre personaggi (usa il {}da il for), e fare lo stesso con il StreamWriterdovrebbe salvarne uno in più.
Luaan,

@Luaan Ho bisogno di esplicitamente Flushil StreamWriterper farlo funzionare correttamente.
LegionMammal978,

22

Linux ELF / x86, 146 byte

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

Include un'intestazione ELF a 52 byte, un'intestazione di programma a 32 byte, 111 byte di codice programma + 3 byte di codice per saltare all'interno delle intestazioni.

Informazioni su come creare piccoli eseguibili ELF sono disponibili all'indirizzo breadbox s' ' un turbine un'esercitazione sulla creazione Davvero Teensy ELF eseguibili per Linux ' .

Linux / i386 usa la socketcall(2)chiamata di sistema multiplex, che accetta ebxla chiamata socket specifica (le SYS_*macro da /usr/include/linux/net.h) e in ecxun puntatore all'area argomento della chiamata alla libreria originale.

Alcune cose fatte per mantenere piccolo l'eseguibile:

  • Presuppone che i registri siano azzerati al momento dell'entrata, cosa che fa Linux, ma non è richiesto dallo standard ELF (l'unico requisito è che ai EDXpunti di ingresso una funzione di finalizzazione (utile per gli eseguibili caricati dal linker dinamico) o sia NULL).
  • Presuppone all'avvio (in genere da una shell) i soli descrittori di file aperti sono 0, 1 e 2. Il che significa che il socket di ascolto sarà fd 3 e il socket accettato sarà fd 4.
  • Presuppone che ci siano esattamente 2 argomenti (incluso argv[0]).
  • Lo stesso spazio stack viene riutilizzato per le chiamate a bind(2), listen(2)e accept(2).
  • Per saltare i campi phentsizee phnum, viene anteposto un byte, trasformandolo in CMPun'operazione che prende immediatamente i campi phentsizee phnum(trucco ingannevolmente rubato dalla soluzione breadbox a 123 nel golf dell'anarchia ).
  • Le operazioni di stringa x86 LODS(caricamento nell'accumulatore e nell'indice di origine di incremento / decremento) e STOS(memorizzazione dall'accumulatore e indice di destinazione di incremento / decremento) sono utili per il codice funzione.
  • XCHG EAX, regè 1 byte, rispetto a MOV EAX, reg, che richiede 2 byte.
  • CDQ/CLTD(sign-extension EAXinto EDX:EAX) può essere usato come un modo a 1 byte per azzerare il EDXregistro.
  • BSWAPè utile per l'implementazione htons().

Fonte Nasm:

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
Questa risposta è poco apprezzata.
cat

16

NodoJS, 146 134 127 byte

require('http').createServer((q,s)=>s.end(eval(0+q.socket.remoteAddress.replace(/^.*:|\./g,'+'))+'\n')).listen(process.argv[2])

Finalmente riesco a pubblicare una risposta NodeJS! IPv4 solo ora.

Esecuzione del campione: node script.js 1024. Da un altro terminale:

$ curl 127.0.0.1:1024
128

2
In questo momento conto 127 byte, anche se puoi ridurlo a 126 scambiando '\n'con una stringa di modello contenente una nuova riga letterale.
Mwr247,

Ciò non avrebbe mancato ai requisiti perché la creazione di un server HTTP, intendo dire, è tecnicamente un server TCP, ma non potresti semplicemente utilizzare il modulo TCP e salvare un personaggio?
MayorMonty

14

Tcl, 92

  • 1 byte salvato grazie a @DonalFellows.
proc s {c a p} {puts $c [expr [string map .\ + $a]]
close $c}
socket -server s $argv
vwait f

Abbastanza autoesplicativo:

socket -server s $argv crea un socket di ascolto sulla porta specificata negli argomenti.

Ogni volta che arriva una nuova connessione, proc sviene chiamato, con parametri come canale, indirizzo di origine e porta di origine. string mapsostituisce .per +l'indirizzo sorgente, e exprvaluta aritmeticamente il risultato, che è poi putsdi nuovo al canale di collegamento c.

vwait esegue un ciclo di eventi per rilevare gli eventi di connessione in entrata.


Ringraziamo @DonalFellows per quanto segue:

Ecco una versione che gestisce IPv6 (richiede Tcl 8.6; la maggior parte della lunghezza extra è dovuta alla produzione di una risposta esadecimale):

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

1
L'uso applynon sembra salvare nulla. Né puoi usarlo tcl::mathop::+ {*}[split $a .]perché è leggermente più lungo. Né puoi radere nulla dai nomi delle opzioni. Ma supportare IPv6 è piuttosto banale da aggiungere, e costa solo pochi byte di codice in più (e quindi un regsubapproccio basato su questo è altrettanto lungo).
Donal Fellows

ahhh, Tcl / Tcl-DP ... incredibile gruppo di strumenti. (negli anni '90 un professore ci ha mostrato che potremmo scrivere un Excel distribuito in rete (con una griglia e inclusa la valutazione delle formule!) condiviso tra più persone con (iirc) 4 (brevi) righe per il server e 5 per i client. ..
Olivier Dulac,

proc s {c a p}hai davvero bisogno di tutto quello spazio bianco?
gatto

12

Groovy 133 , 125 , 93 , 89

new ServerSocket(args[0]as int).accept{it<<(it.inetAddress.address as int[]).sum()+"\n"}

Solo IPv4, probabilmente.

Ungolfed:

new ServerSocket(args[0]as int).accept{
    it << (it.inetAddress.address as int[]).sum()+"\n"
}

test:

$ telnet localhost 9000
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
128
Connection closed by foreign host.

1
.toInteger()as inte s.inetAddress.address*.toInteger()(s.inetAddress.address as int[]). E dopo c'è uno spazio extra .with.
arte

@manatwork thx! Aggiornato.
Will Lp

9

Python 3, 170 166 147 byte

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()

Porta su stdin, solo IPv4. Funziona su GNU / Linux (e, presumo, la maggior parte degli altri unices), che si espande automaticamente "" a "0.0.0.0", ma non sono sicuro di Windows.


2
È possibile salvare diversi byte. In primo luogo, gli spazi dentro import *e , SOCK_STREAMnon sono necessari. Inoltre, la riga di invio potrebbe essere scritta in modo più efficiente come c.send(b"%d\n"%eval(a[0].replace(".","+"))).
Hannes Karppila,

2
@HannesKarppila oh, grazie. dimenticato gli spazi, l'hack eval è piuttosto bello però.
Sammko,

2
AF_INET e SOCK_STREAM sono solo costanti; AF_INET è 2 e SOCK_STREAM è 1. Inoltre, come detto, SOCK_STREAM non è necessario; così puoi accorciarlo invece usando s=socket(2).
Skyler,

1
non puoi semplicemente fare socket () e quindi salvare un altro byte?
Foon,

1
Puoi salvare 10 caratteri usando Python 2. Quindi, int(input())diventa input()e la parte di invio diventac.send(`eval(a[0].replace(".","+"))`)
Blender

9

Java, 371 368 350 344 333 310 295 282 byte

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]);
            }
        }
    }
}

Produzione

mallard@steamroller:~$ telnet localhost 8888
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
128
Connection closed by foreign host.

1
Rimuovi int k=e sostituisci k con tutte le cose dentro Integer.toString(k). Per salvare alcuni byte.
GiantTree

1
Javas byte abbastanza sicuro incasina il valore di ritorno per 192.168.2.1 o indirizzi simili con un byte superiore a 127.
AlexR

1
La modifica interfacea classdovrebbe guadagnare qualche byte in più
ortis

2
Usa a.getOutputStream().write((c[0] + c[1] + c[2] + c[3]+"\n").getBytes());invece dinew DataOutputStream(a.getOutputStream()).writeBytes(c[0] + c[1] + c[2] + c[3] + "\n")
ortis

3
Non è try(Socket a=...){}più breve di a.close();? Richiede Java 7, ma può guadagnare byte.
Olivier Grégoire,

8

PowerShell v2 +, 303 268 257 227 byte

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()}

Ho salvato 35 byte grazie a Matt ... Ho salvato altri 11 byte con aliasing New-Objecte piccole modifiche ... Hai salvato altri 30 byte utilizzando implicitamente localhost anziché anyindirizzo IP e corretto per tenere conto dell'utilizzo continuo come originariamente specificato e ho perso

Veramente simile alla risposta C # , dato che è .NET alla base di entrambi. Risparmiamo alcuni byte qui sulla risposta C # essendo in grado di sfruttare la funzionalità di restituzione di PowerShell (che circonda la nostra dichiarazione / assegnazione in parentesi e quindi chiamare immediatamente i metodi.), Ma perdiamo moltissimo perché abbiamo bisogno di formulare la somma . Il fatto che abbiamo nomi / chiamate di classe leggermente più brevi è davvero il motivo per cui questa risposta batte C #.

Spiegazione

Per prima cosa creiamo un New-Alias(con l' nalalias) per risparmiare sulla riscrittura in New-Objectseguito. Il resto della prima riga sta configurando un listener TCP. Passiamo la riga di comando $args[0]come input per la creazione di un nuovo System.Net.Sockets.TcpListener, archiviato come $l. Quell'oggetto è incapsulato in parentesi e immediatamente chiamato con .Start()per aprire attivamente il socket.

Entrando in un forciclo infinito , impostiamo quindi il nostro listener $lsul blocco con il AcceptTcpClient()quale aspetteremo una connessione. Un riferimento a quella connessione (una volta effettuata) viene archiviato $c, incapsulato in parentesi e immediatamente chiamato GetStream()per ottenere il flusso di dati. Tale flusso di dati viene passato a un nuovo System.IO.StreamWritercostruttore $w, quindi possiamo manipolarlo. Quel costruttore è esso stesso incapsulato in parentesi e immediatamente chiamato Write(...).

All'interno della Write(...)chiamata, prendiamo la gestione del nostro cliente $ce otteniamo la RemoteEndPointproprietà del cliente . Questo è l'unico modo (che ho trovato finora) per ottenere l'indirizzo IP remoto. Successivamente, è necessario ripetere il cast come [System.Net.IPEndPoint]oggetto in modo che sia formattato correttamente, incapsularlo in parentesi e estrarre solo la .Addressproprietà. Quindi -replacei periodi letterali con i segni più, quindi reindirizziamo a Invoke-Expression(simile a eval) per ottenere la nostra somma.

Dopo la scrittura dell'IO, è necessario chiamare .Dispose()per assicurarsi che il flusso di dati sia scaricato nel client e chiuso. Il server TCP interrompe la connessione client senza preavviso, quindi a seconda del client utilizzato potrebbe bloccarsi per un po 'a questo punto. Quindi continua attraverso il forloop senza chiudere correttamente le connessioni. Questo significa anche che perde la memoria e gestisce il sistema come un matto, ma non ci interessa, vero? Tuttavia, potrebbe essere necessario utilizzare Task Manager per terminare il processo al termine dell'esecuzione del server. : D

Anche solo IPv4, dato che la somma si abbassa in modo spettacolare cercando di gestire un indirizzo IPv6, poiché :non è un operatore algebrico valido per iexl'analisi.


2
"Perdita di memoria e gestione del sistema come un matto" Cosa, hai free()dopo? delete[], può essere? : P
cat

8
@tac Sì, c'è un sacco di metodi .close()e .dispose()metodi che non chiamiamo qui che potrebbero indurre le persone in Code Review a adattarsi.
AdmBorkBork,

Oh, PS GC non è? Oppure il GC esegue il conteggio e non l'analisi dell'ambito?
gatto

@tac Sì, PowerShell ha la garbage collection grazie al sistema .NET sottostante. Ma, a seconda di come stai chiamando o sfruttando questo script, puoi imbatterti in bug come questo che perde memoria nella pipeline. Inoltre, il codice sopra non è thread-safe e quindi può incorrere in problemi GC con quello, poiché non stiamo chiudendo esplicitamente il socket.
AdmBorkBork,

1
Durante i test non sono riuscito a farlo funzionare, probabilmente a causa di problemi del firewall che non mi sento di risolvere, quindi non posso esserne sicuro ma ..... Penso che puoi eliminare "Sistema" dalla maggior parte se non tutti i tipi di cast hai lì cioè: [Net.ipaddress]::Anyfunziona.
Matt,

7

PHP, 161 (56?)

Questo è il mio primo post qui. Spero che vada bene :)

<?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
    }

Terminale:

$ php test.php 8080 &
$ telnet localhost 8080
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
128
Connection closed by foreign host.

Funziona solo con IPV4

Modifica : ho appena notato che php supporta il server di base:
ho deciso di attenermi al conteggio dei caratteri originale a meno che qualcuno non confermi se è consentito seguire :)

test2.php: (possibile soluzione a 56 byte)

<?=array_sum(explode('.',$_SERVER['REMOTE_ADDR']))."\n";

E quindi avviare il servizio con:

php -S localhost:8080 test2.php

Chrome come client immagine dello schermo

Modifica 2: wget come client

$ wget -qO- localhost:8080
128

So che le regole dicono: "Il programma o la funzione legge l'intero N da argomenti o stdin", ma va bene se il programma in questo caso è php stesso? O l'utilizzo del server integrato in php è considerato una scappatoia?
Mikael,

Benvenuto in Programmazione di puzzle e codice golf! La tua soluzione da 161 byte ha un bell'aspetto. La soluzione a 56 byte che hai citato è quella sotto test2.php? In tal caso, penso che dovresti chiedere al PO se considererebbero quel tipo di built-in accettabile per questa sfida. Non è una scappatoia però.
Alex A.

Direi che l'uso di un server TCP incorporato sarebbe accettabile, ma in questo caso parliamo di un server HTTP incorporato . Quindi la soluzione a 56 byte 1) non fa nulla se il client si connette e non invia nulla; 2) restituisce solo "[Mer 30 Mar 10:15:02 2016] 127.0.0.1:47974 Richiesta non valida (richiesta HTTP non valida)" senza eseguire test2.php nel caso in cui il client invii ad esempio "pippo"; 3) invia un set completo di intestazioni di risposta HTTP prima della risposta effettiva richiesta nel caso in cui il client invii una richiesta HTTP valida.
arte

@Alex A. Grazie e sì, la soluzione a 56 byte è sotto test2.php :)
Mikael

@manatwork Hai ragione, ma stavo pensando che il cliente non sia chiaramente specificato in questo compito. Quindi va bene usare il browser o ancora più semplice qualcosa come "wget ​​-qO- localhost: 8080" come client?
Mikael,

7

Vai , 359 311

Questo è il mio primo programma su Go - Mi ha permesso di scoprire una cosa: questo non è sicuramente un buon linguaggio per il golf!

(Complimenti a @steve che ha fatto la maggior parte del golf!)

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
Ma è sicuramente un bel linguaggio per creare un server tcp!
Numeri,

1
Strano, sto ottenendo il risultato 360 quando mi collego da 192.168.0.67, anziché 427.
Steve

3
È possibile denominare i pacchetti stringhe + strconv per salvare alcuni byte. ad esempio "strings"diventa s "strings"così che il successivo strings.Splitdiventa giusto s.Split.
steve

1
Ancora pochi byte cancellati da pastebin.com/HY84sazE - ora inizia a sembrare un po 'più "golfato"
Steve

2
Se si utilizzano import(."pkgname")tutte le funzioni verranno importate nello spazio dei nomi corrente, è quindi possibile eliminare il prefisso. per esempio. import ."fmt"; Println("foo") Se usi Sscanfdal fmtpacchetto per analizzare l'indirizzo invece di regex, ti farà risparmiare qualche altro byte, dandoti il ​​piacevole bonus di dover Fprintlnrestituire il totale invece di importare strconv.
Kristoffer Sall-Storgaard

7

Lisp comune, 110 byte

(use-package'usocket)(lambda(p)(socket-server"localhost"p(lambda(u)(format u"~D~%"(reduce'+ *remote-host*)))))

Dettagli

(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
Yay per Lithp comune!
gatto

6

q, 88 byte

system raze"p ",1_.z.x;.z.pg:{(string sum"i"$0x0 vs .z.a),"\n"};.z.ph:{.h.hy[`;.z.pg[]]}
  • system raze"p ",1_.z.x: Accetta il secondo argomento della riga di comando (il primo "-"serve a dire di qnon interpretare Ncome uno script / file) e apre una porta ( "p ") con esso.
    • Nota: la chiamata q -p Nimposta Nautomaticamente la porta , ma poiché la domanda sembra suggerire che Ndovrebbe essere un argomento per il programma piuttosto che l'eseguibile stesso, ho fatto un passo più lungo.
  • All'interno della .z.pgfunzione che gestisce le richieste in arrivo, .z.acontiene l'indirizzo IP come numero intero a 32 bit.
    • "i"$0x0 vslo divide in "componenti" interi e sumfa la somma.
    • Infine, stringil risultato numerico e accodarlo "\n"per tornare al client.
  • .z.ph è un'altra funzione per le richieste GET HTTP, con ulteriore gestione per convertire l'output di stringa in una risposta HTTP valida.

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"$0x0 vs .z.a),"\n"};.z.ph:{.h.hy[`;.z.pg[]]}
q)

Demo - Client (da un'altra qsessione in esecuzione 127.0.0.1):

q)(hopen `::1234)""
"128\n"

Demo - Client (da curl):

$ curl localhost:1234
128

$

6

LiveScript, 107 105 byte

(require \http)createServer(->&1.end((.reduce (+))<|it.connection.remoteAddress/\.))listen process.argv.0

Non c'è molto altro da aggiungere, è solo roba di base su NodeJS. Punti di stile per &1(secondo argomento), <|(tubazioni F #, affine a $in Haskell) e biop: (+)in LS è come una sezione operatore in Haskell: una funzione binaria al curry (che aggiunge i suoi operandi). Anche un po 'sporco: /se viene dato una stringa letterale alla sua destra, si dividerà.


5

Perl, 141 132 + 1 = 133 byte

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;
}

Esempio

$ 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.
$

Sei sicuro che sia corretto? Ricevo la somma stampata nel terminale del server, non in quella del client. Ad ogni modo, puoi rimuovere tutte le parentesi e cambiare s/\./+/gy/./+/.
arte

Ahh, frainteso ... revisionerai di conseguenza e incorporerai il tuo buon suggerimento.
steve

1
while(1){…}{…;redo}secondo l' ottimo consiglio di user130144 . E ad eccezione della chiamata, tutte le altre parentesi non sono necessarie. ->send()
arte

4

Python 2, 180 byte

from SocketServer import*
TCPServer(('',input()),type('',(BaseRequestHandler,set),{'handle':lambda s:s.request.send(`eval(s.client_address[0].replace('.','+'))`)})).serve_forever()

Prende il porto su stdin.


4

NodeJS (ES6), 129 118 107 byte

require('net').createServer(c=>c.end(eval(c.remoteAddress.replace(/\./g,'+'))+`
`)).listen(process.argv[2])

Funziona per IPv4. Correre comenode server.js <port>


In realtà non funziona se il server utilizza IPv6 (come, ad esempio, il mio funziona automaticamente), poiché c.remoteAddresssarebbe allora ::ffff:127.0.0.1. (Ho testato su Nodo v5.9.1).
Frxstrem,

Inoltre, non hai una nuova riga finale, che dovrebbe aumentare il tuo punteggio di 2 byte.
Frxstrem,

@Frxstrem Whoops, ho dimenticato quella nuova riga. Aggiunge solo 1 byte però grazie alle stringhe del modello. Per quanto riguarda la famiglia IP: .listen()usato per impostazione predefinita su IPv4, ma sembra che sia cambiato per errore o design. L'invio funzionerà correttamente nelle versioni più recenti del nodo quando IPv6 è disabilitato sul computer host.
Mwr247,

4

Vai, 211 byte

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()}}

Probabilmente può essere ulteriormente giocato a golf, non sono del tutto soddisfatto del modo in cui devo analizzare l'indirizzo IP, ad esempio, sembra un orribile hack.

Ascolta IPv4 sulla porta fornita come argomento.


4

PowerShell, 208 206 192 152 byte

($t=[net.sockets.tcplistener]$args[0]).start();for(){($z=$t.acceptsocket()).sen‌d([char[]]"$($z.remoteendpoint.address-replace"\.","+"|iex)");$z.close()}

informazioni sulla versione:

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

Grazie a TimmyD per avermi salvato 14 byte!

Grazie infinite a TessellatingHeckler per avermi salvato 40 byte


@TimmyD ah oops Ho perso quello che era necessario ... risolto ora
Nacht

Uno dei modi in cui i programmi sono autorizzati a ricevere input è da stdin. suppongo che questa domanda particolare non lo specifichi come consentito, ma è una cosa generale di code-golf che penso dovrebbe contare per PowerShell. Sfortunatamente è diverso da bash in quanto non attende input su stdin se non ne è stato fornito nessuno.
Nacht,

giusto. riparato di nuovo
Nacht

Bene, ora per alcuni golf - prova quanto segue a 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()}
AdmBorkBork

1
Penso che puoi abbassare questo valore a 152: rilasciare new-object e lanciare direttamente, saltare la conversione di array di byte e fare una stringa cast in modo diverso, non memorizzare affatto $ x e rilasciare i parametri rimanenti per send (), e diventa ($t=[net.sockets.tcplistener]$args[0]).start();for(){($z=$t.acceptsocket()).send([char[]]"$($z.remoteendpoint.address-replace"\.","+"|iex)");$z.close()}- che ho testato rapidamente solo con la connessione netcat, ma sembra funzionare lo stesso - connettendosi comunque da localhost.
TessellatingHeckler

4

8086 codice macchina (DOS a 16 bit), 163 156 148 148 142 byte

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

Codice assembly equivalente:

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

Ciò presuppone che ntcpdrvsia caricato in INT 0x61(e qualsiasi driver di pacchetto adatto in 0x60). Compila con fasm tcpserv.asm.

Ha alcuni problemi però:

  • Non controlla se l'argomento è un numero di porta valido o se è addirittura un numero.
  • Il client deve inviare almeno un byte, poiché non riesco a trovare un altro modo per sapere se un client si è connesso.
  • Funziona solo una volta e si blocca su un secondo tentativo. Funziona di nuovo dopo un riavvio.
  • Il valore restituito viene riempito a sinistra con zero.
  • Questa è la mia prima entrata in golf e anche il mio primo programma asm 8086. Sono sicuro che ci sono modi per migliorare ulteriormente questo.

1
Puoi semplicemente pubblicare un hexdump dell'output compilato per 148 byte
cat

È permesso?
Renderebbe

1
Bene, ho cambiato la voce in codice macchina. Anche rasato qualche byte in più usando xor r,rinvece di mov r,0.
user5434231

1
L'ho scritto su una macchina dos dove si trovano le nuove linee CR LF, quindi sono andato con quello. Ad ogni modo, è quasi inutile contare ora le dimensioni dell'asm, potrebbe anche ripulirlo un po 'e aggiungere alcuni commenti.
user5434231

1
Questo dovrebbe succedere anche qui, e funziona; int 0x61restituisce una porta locale casuale in ax. Ma cambia anche l'IP di ascolto in un numero di immondizia ( 4.2.0.0iirc)
user5434231

3

Haskell, 216 byte

Utilizzo del pacchetto "network-simple" ( cabal install network-simple). Ha bisogno di un paio di estensioni di lingua ( -XOverloadedStrings -XNoMonomorphismRestriction) per funzionare.

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)

Esistono un paio di possibili semplificazioni, tra cui la modifica della wfunzione per restituire la somma direttamente anziché un elenco e l'utilizzo di una funzione anziché di un programma in modo che il numero di porta possa essere specificato come argomento. Tuttavia, non immagino che ciò ridurrebbe molto le dimensioni. 20 byte forse?


Bello! Abbastanza sicuro che puoi ancora eliminare alcuni byte rinominando win #, quindi w h ndiventa h#nper un risparmio di 2 byte per utilizzo.
Actorclavilis,

3

Parotite, 114 115 byte

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

Questa è la versione InterSystems Caché di Mumps - se esiste una versione là fuori che può acquisire un indirizzo TCP più breve di ##class(%SYSTEM.TCPDevice).PeerAddr() (dato che è quasi un terzo dell'intero programma) potrebbe avere una migliore possibilità rispetto ad alcune delle altre lingue già pubblicate ... ;-)

Modifica: grazie a @TimmyD - Ho perso la lettura della porta da STDIN o argomenti invece di essere hardcoded. Modificato; ha aggiunto 1 byte al programma.


@TimmyD - Ah, hai ragione. Perso quello leggendo i requisiti. Modificherà posthaste.
zmerch,

3

C, 535 byte

Bene, qualcuno ha dovuto farlo.

Ho aggiunto un'interruzione di riga singola in modo che il codice pubblicato contenga effettivamente 536 caratteri.

#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;}

compilare con gcc [file_name] -o server

Corri con ./server [port]

connesso con telnet localhost [port]


3
Bella risposta! Come accennato in precedenza , è possibile salvare alcuni byte utilizzando i valori effettivi per alcune costanti, come AF_INET e SOCK_STREAM.
Hannes Karppila,

2

Java, 210 byte

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());}}};

Allargato:

@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());
      }
    }
}

Questa è una raccolta di tutti i suggerimenti che ho dato in altre risposte Java, oltre alla scrittura come funzione anziché come programma completo, che guadagna circa 70 byte rispetto al programma.


2

Haskell, 326 byte

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)

Purtroppo ho dovuto usare Network.Socketper accedere all'indirizzo IP remoto come numero intero anziché come stringa. E avrebbe salvato decine di personaggi, se solo potessi fare s <- listenOn (PortNumber n), invece di dover chiamare in modo esplicito socket, binde listensingolarmente. Ma, purtroppo, Network.acceptmi dà una stringa host , non un numero intero di indirizzi IP , quindi ho dovuto ricorrere ad Network.Socket.acceptamici.

La funzione faccetta un numero di porta come argomento e crea un socket server ( s) in ascolto su quella porta. Quindi chiama la funzione gcon il socket del server. gloop per sempre, accettando connessioni. La funzione baccetta un indirizzo IPv4 effettivo e calcola la somma delle sue cifre.

Sono sicuro che qualcuno da qualche parte può farlo meglio di me. Volevo mostrare quanto fossero dannatamente facili i socket di Haskell ... ma poi ho fallito miseramente, perché ho bisogno di accedere all'indirizzo IP, che di solito non è facile da ottenere.


Il pacchetto "network-simple" fornisce un'interfaccia molto più piacevole che passa SockAddr a una funzione che gli viene fornita, che semplifica le cose. Vedi la mia soluzione che sto per pubblicare ...
Jules

Sono evidenti alcune semplificazioni: (1) credo withSocketsDosia necessario solo su Windows, quindi se si esegue su Linux può essere ignorato; (2) 0xFF è un carattere più lungo di 255; (3) la conversione del socket in un handle e l'utilizzo di IO normali sono molto più lunghi rispetto all'utilizzo Network.Socket.send. Sì, sendè obsoleto, ma il motivo non è rilevante per questo scenario (riguarda solo testo non ASCII o dati binari), quindi sembra ragionevole utilizzarlo.
Jules,

Network.accept gives me a host string, not an IP address integerNon puoi semplicemente dividere la stringa IP su ".", mapla funzione stringa-numero di Haskell sulla stringa divisa e sommare i risultati?
cat

2

Lua, 169 162 160 153 151 148 138 129 byte

Versione golfizzata

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

Richiede l'installazione di Luasocket e un interprete che supporti le etichette. L'ho provato con Luajit e posso anche confermare che il codice non funziona con Lua 5.1.

Versione Ungolfed

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

Modifica 1:

Modificato i=({c:getpeername()})[1]in soloi=c:getpeername()

Modifica 2:

Parentesi graffe rimosse dall'istruzione obbligatoria.

Modifica 3:

Rimosse le parentesi graffe attorno al vararg, diminuito un po 'il conteggio dei byte.

Modifica 4:

Rimossa la parentesi attorno a "% d +", più corta di 2 byte.

Modifica 5:

Rimossa la variabile non necessaria i.

Modifica 6:

Modificato l'ip da "127.0.0.1" a 0. (Grazie a xyzzy su #lua)

Modifica 7:

Rimossa la chiamata di funzione al numero poiché le stringhe vengono automaticamente lanciate sui numeri (Grazie a Trebuchette per il suggerimento, non lo sapevo)


1
Solo Lua 5.2 e successive supportano le etichette, se sei curioso
Trebuchette

1
Inoltre, Lua lancia automaticamente le stringhe in numeri con l' +operatore, in modo da poter estrarre tonumber.
Trebuchette,

2

Haskell, 185 (+ 19 = 204)? byte

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)

Accetta il numero di porta come una riga su stdin; richiede network-simpledalla Cabala.

Come al solito con le risposte di Haskell che non si limitano a funzioni pure, importsoccupano troppi byte. La nuova riga finale vale anche 9 byte ...

Un po 'simile alla risposta di @Jules, ma uso la manipolazione di stringhe invece delle operazioni sui byte. Ho rubato anche l' -XOverloadedStringsestensione, che probabilmente vale 19 byte in più.


2

C, 243 188 byte (o forse 217 162 byte)

V2: vedi sotto per le spiegazioni.

188 byte:

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]);}

Leggermente circospetto 162 byte:

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]);}

Probabilmente più golf possibile domani mattina. Metterò in ordine questo post dopo quegli aggiornamenti.


V1:

Questo è stato davvero divertente da giocare a 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);}}

Funziona con IPv4. Principalmente è un'implementazione semplice. I tre componenti principali sono

Creazione del socket:

struct sockaddr_in S = {2, htons (atoi (v [1]))}, C; bind (s = socket (2,1,0), & S, g = 16);

Usiamo le varie forme esplicite delle costanti AF_INET ecc. E facciamo uso del fatto che quando una struttura viene inizializzata in C in questo modo gli elementi non specificati vengono impostati a zero.

Ascolta i client, accettali e chiudi le connessioni:

per (ascolta (s, 8); c = accettare (s, e C, e g); q = fclose (g))

Infine per inviare a ciascun cliente i dati:

per (g = 4; g; q + = C.sin_addr.s_addr >> 8 * - g & 255); fprintf (g = fdopen (c, "w"), "% d \ n", q);

L'IP è memorizzato C.sin_addr.s_addrcome un intero a 32 bit in cui ogni ottetto è rappresentato da uno dei quattro byte. Sommiamo questi byte con il ciclo for e quindi li stampiamo sullo stream usando fprintf.

Ho una soluzione più corta di 217 byte ma non sono del tutto sicuro che non violi le scappatoie standard poiché richiede che la porta sia fornita in modo unario nell'ordine dei byte di rete come argomenti della riga di comando. Cioè, per eseguire il server sulla porta 12345 è necessario chiamare

$ ./tcp 1 1 1 1 ... 1 1 1

dove il numero totale di 1s è 14640. Per non dire altro è un po 'ingombrante. Ma eccolo comunque:

#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);}}

2

Racchetta, 265 byte

#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)))

2

Fattore, 155 146 131 206 190 byte

Bene, ho appena imparato molto sulla programmazione di socket di basso livello. Io non credo di aver mai voglia di farlo di nuovo, perché la mia thr fa male la testa.

[ 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 sì, filettato e non ritorna, giusto.


Puoi usare 10 base>invece di string>number?
fede s.

@fedes. Wow, non ho mai saputo che esistesse. Penso che questo mi permetterà di abbreviare molte delle mie risposte a Fattore!
gatto

E anche 10 >baseper numero> stringa.
fede s.

1
@fedes. Quelli meritano una risposta qui : D
cat
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.