Un servidor TCP simple

104

Escriba un programa o función que escuche el tráfico TCP entrante en el puerto N. Ofrece un servicio simple: calcula la suma de los campos de dirección IP de la conexión entrante y los retornos.

El programa o la función lee el entero N de argumentos o stdin. Escucha las conexiones TCP entrantes en el puerto N. Cuando alguien se conecta a ese puerto, el programa calcula la suma de sus campos de dirección IP y lo envía de vuelta al cliente con la nueva línea final y cierra la conexión.

  • El número de puerto N es un puerto válido y 2 10 <N <2 15
  • La nueva línea final puede ser \no\r\n
  • Puede usar IPv4 o IPv6. Dado que las direcciones IPv6 están escritas en forma hexadecimal, también debe proporcionar el resultado en el mismo formato, por ejemplo 2001:0db8:0000:0042:0000:8a2e:0370:7334 => 12ecd.

Este es el . Se aplican reglas estándar y lagunas.

Ejemplo

Ejecutas tu servidor con ./server 1234. El servidor ahora se está ejecutando y esperando conexiones en el puerto 1234. Luego, un cliente de se 127.0.0.1conecta a su servidor. El servidor realiza un cálculo simple: 127+0+0+1 => 128y envía el resultado al cliente (con arrastrarse nueva línea): 128\n. Luego el servidor cierra la conexión y espera al próximo cliente.

Tabla de clasificación

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>

Hannes Karppila
fuente
1
¿Está permitido usar inetd / xinetd o similar?
Trauma digital
9191
Me gusta esto, ya que es un desafío de golf en el que es improbable que los idiomas de golf sean muy buenos.
isaacg
99
No solo es sorprendente que un servidor TCP sea aparentemente un programa muy fácil de escribir, sino que estoy completamente desconcertado por el hecho de que se está jugando al golf por diversión. Volveré a luchar con FizzBuzz como un imbécil.
MonkeyZeus
17
@isaacg Solo es hora de que alguien encuentre el servidor TCP incorporado en Mathematica
Downgoat
3
@MonkeyZeus Para ser justos, no verá ningún buen servidor TCP aquí. Hacer un servidor TCP confiable y escalable que maneje bien todas las complejidades de TCP (y el protocolo de su aplicación) es un poco más difícil: D Aunque ciertamente ayuda que el protocolo sea extremadamente simple: ni siquiera necesita leer la transmisión, algo que he visto roto en demasiados servidores TCP para contar: D
Luaan

Respuestas:

57

Bash + netcat + ss + ..., 65 60 caracteres

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

No es una solución seria, solo sentía curiosidad por esta posibilidad.

Gracias a:

  • ninjalj por sugerir el awkfiltrado basado (-5 caracteres)

Ejecución de muestra:

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

En Ubuntu puede obtener ncde netcat-traditional (no, netcat-openbsd no es bueno) y ssde iproute2 .

hombre trabajando
fuente
22
¿Por qué dices que no es una solución seria? Mientras funcione como se esperaba, no veo ninguna razón por la que no deba considerarse serio. También es el más corto por un margen bastante significativo en este momento.
Alex A.
La mayor preocupación en su contra apareció durante la discusión con @JesseSielaff cuando supe que en los sistemas con IPv6 configurado, la información relacionada con el socket puede tener un formato diferente. No tiene tal sistema para probarlo. Para lo cual estoy pensando si sería más correcto convertirlo en CW.
manatwork
3
Entiendo que las especificaciones son compatibles con IPv4 o IPv6, no con ambas. Entonces, siempre que funcione para IPv4, no debería ser compatible con IPv6, creo.
Alex A.
1
@AlexA. Al menos creo que mi pregunta lo dice. ¿Debo aclararlo?
Hannes Karppila
@HannesKarppila, tu pregunta es clara. El posible problema es que mi solución puede requerir que el sistema operativo esté configurado de una manera particular para poder ejecutarse. Así que me preocupa porque puede fallar si se configura IPv6, independientemente de si lo manejo o no. Alguien que tenga configurado IPv6 podría decirlo con seguridad ...
manatwork
23

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

Ejemplo clásico de un servidor básico C # TCP. Pruebas:

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

LegionMammal978
fuente
77
Puede guardar 1 Byte usando en int Mainlugar de void Main. Como el programa nunca regresa, el compilador no requiere una returndeclaración.
raznagul
Y no, no tiene fugas. En realidad, también es bastante determinista sobre la liberación de recursos. Además, el argumento de Startes opcional, guardando otro carácter.
Luaan
@Luaan Sí, eso quedó de la depuración.
LegionMammal978
Además, puede usar usingen el TcpClient, que le ahorrará tres caracteres más (use el {}de for), y hacer lo mismo con el StreamWriterdebería guardar uno más.
Luaan
@Luaan necesito explícitamente Flushel StreamWriterde hacer que funcione correctamente.
LegionMammal978
22

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

Incluye un encabezado ELF de 52 bytes, un encabezado de programa de 32 bytes, 111 bytes de código de programa + 3 bytes de código para saltar dentro de los encabezados.

Puede encontrar información sobre cómo crear pequeños ejecutables ELF en el " A Whirlwind Tutorial de breadbox " sobre cómo crear ejecutables ELF realmente para Teensy para Linux " .

Linux / i386 usa la socketcall(2)llamada al sistema multiplex, que toma ebxla llamada de socket específica (las SYS_*macros de /usr/include/linux/net.h), y en ecxun puntero al área de argumento de la llamada a la biblioteca original.

Algunas cosas hechas para mantener el ejecutable pequeño:

  • Se supone que los registros se ponen a cero en la entrada, lo que Linux hace, pero no es requerido por el estándar ELF (el único requisito es que en los EDXpuntos de entrada a una función de finalización (útil para ejecutables cargados por el enlazador dinámico) o sea NULL).
  • Se supone que en el inicio (generalmente por un shell) los únicos descriptores de archivo abiertos son 0, 1 y 2. Lo que significa que el socket de escucha será fd 3 y el socket aceptado será fd 4.
  • Se supone que hay exactamente 2 argumentos (incluidos argv[0]).
  • El mismo espacio de pila se reutiliza para las llamadas a bind(2), listen(2)y accept(2).
  • Para omitir los campos phentsizey phnum, se antepone un byte, que se convierte en una CMPoperación que toma los campos phentsizey phnumcomo un inmediato (truco robado descaradamente de la solución de breadbox a 123 en anarchy golf ).
  • Las operaciones de cadena x86 LODS(carga en el acumulador y el índice de origen de incremento / decremento) y STOS(almacenar desde el acumulador y el índice de destino de incremento / decremento) son buenas para el código corto.
  • XCHG EAX, reges de 1 byte, en comparación con MOV EAX, reg, que toma 2 bytes.
  • CDQ/CLTD(sign-extend EAXinto EDX:EAX) puede usarse como una forma de 1 byte para poner a cero el EDXregistro.
  • BSWAPes útil para la aplicación htons().

Fuente 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
ninjalj
fuente
44
Esta respuesta es muy poco apreciada.
gato
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])

¡Finalmente puedo publicar una respuesta de NodeJS! IPv4 solo en este momento.

Ejecución de la muestra: node script.js 1024. Desde otra terminal:

$ curl 127.0.0.1:1024
128
nickb
fuente
2
Cuento 127 bytes en este momento, aunque puede reducirlo a 126 intercambiando '\n'con una cadena de plantilla que contiene una nueva línea literal.
Mwr247
¿No fallarían los requisitos porque estás creando un servidor HTTP, es decir, técnicamente es un servidor TCP, pero no podrías simplemente usar el módulo TCP y ahorrarte un personaje?
MayorMonty
14

Tcl, 92

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

Bastante autoexplicativo:

socket -server s $argv crea un socket de escucha en el puerto especificado en los argumentos.

Cada vez que llega una nueva conexión, proc sse llama al, con el canal, la dirección de origen y el puerto de origen como parámetros. string mapsustituye .a +en la dirección de origen y exprevalúa aritméticamente el resultado, que luego putsvuelve al canal de conexión c.

vwait ejecuta un bucle de eventos para capturar los eventos de conexión entrantes.


Crédito a @DonalFellows por lo siguiente:

Aquí hay una versión que maneja IPv6 (requiere Tcl 8.6; la mayor parte de la longitud adicional se debe a que produce una respuesta hexadecimal):

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
Trauma digital
fuente
1
Usar applyno parece guardar nada. Tampoco puedes usarlo, tcl::mathop::+ {*}[split $a .]ya que es un poco más largo. Tampoco puedes afeitar nada de los nombres de las opciones. Pero admitir IPv6 es bastante trivial de agregar, y solo cuesta unos pocos bytes de código más (y luego un regsubenfoque basado en el mismo es igual de largo).
Donal Fellows
ahhh, Tcl / Tcl-DP ... increíble conjunto de herramientas. (en la década de los 90, un profesor nos mostró que podíamos escribir un Excel distribuido en red (con una cuadrícula, ¡e incluso una evaluación de fórmulas!) compartido entre varias personas con (iirc) 4 líneas (cortas) para el servidor y 5 para los clientes. ..
Olivier Dulac
proc s {c a p}¿realmente necesitas todo ese espacio en blanco?
gato
12

Groovy 133 , 125 , 93 , 89

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

Solo IPv4, probablemente.

Sin golf:

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

Pruebas:

$ telnet localhost 9000
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
128
Connection closed by foreign host.
Will Lp
fuente
1
.toInteger()as inty s.inetAddress.address*.toInteger()(s.inetAddress.address as int[]). Y hay un espacio extra después .with.
manatwork
@manatwork thx! Actualizado.
Will Lp
9

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

Toma puerto stdin, solo IPv4. Funciona en GNU / Linux (y, supongo, la mayoría de los otros unices), que se expande automáticamente "" a "0.0.0.0", aunque no estoy seguro acerca de Windows.

sammko
fuente
2
Podrías guardar varios bytes. En primer lugar, los espacios import *y , SOCK_STREAMson innecesarios. Además, la línea de envío podría escribirse de manera más eficiente como c.send(b"%d\n"%eval(a[0].replace(".","+"))).
Hannes Karppila
2
@HannesKarppila oh, gracias. se olvidó de los espacios, sin embargo, el truco eval es bastante bueno.
sammko
2
AF_INET y SOCK_STREAM son solo constantes; AF_INET es 2 y SOCK_STREAM es 1. Además, como se mencionó, SOCK_STREAM es innecesario; para que puedas acortar eso usando en su lugar s=socket(2).
Skyler
1
¿no puedes simplemente hacer socket () y por lo tanto guardar otro byte?
Foon
1
Puede guardar 10 caracteres usando Python 2. Luego, se int(input())convierte input()y la parte de envío se conviertec.send(`eval(a[0].replace(".","+"))`)
Blender
9

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

Sin golf

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

Salida

mallard@steamroller:~$ telnet localhost 8888
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
128
Connection closed by foreign host.
Matthew Smith
fuente
1
Quite el int k=y reemplace el k con todas las cosas c en Integer.toString(k). Para guardar unos pocos bytes.
GiantTree
1
El byte de Javas está bastante confuso con el valor de retorno de 192.168.2.1 o direcciones similares con un byte superior a 127.
AlexR
1
El cambio interfacea classdebería ganar algunos bytes más
ortis
2
Usar en a.getOutputStream().write((c[0] + c[1] + c[2] + c[3]+"\n").getBytes());lugar denew DataOutputStream(a.getOutputStream()).writeBytes(c[0] + c[1] + c[2] + c[3] + "\n")
ortis
3
No es try(Socket a=...){} más corto que a.close();? Requiere Java 7, pero puede ganar bytes.
Olivier Grégoire
8

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

Ahorré 35 bytes gracias a Matt ... Ahorré otros 11 bytes aliasing New-Objecty pequeños ajustes ... Ahorré 30 bytes más al usar implícitamente localhost en lugar de anyla dirección IP y corregí para tener en cuenta el uso continuo como se especificó originalmente y me perdí

Realmente similar a la respuesta de C # , ya que es .NET subyacente a ambos. Ahorramos unos pocos bytes aquí sobre la respuesta de C # al poder aprovechar la funcionalidad de retorno de PowerShell (que rodea nuestra declaración / asignación en parens, y luego llamar inmediatamente a los métodos.), Pero perdemos mucho al necesitar formular el resumen. . El hecho de que tengamos nombres / llamadas de clase un poco más cortos es realmente por qué esta respuesta está superando a C #.

Explicación

Primero creamos un New-Alias(con el nalalias) para ahorrar en volver a escribir New-Objectmás tarde. El resto de la primera línea está configurando un escucha TCP. Pasamos la línea de comandos $args[0]como entrada para crear un nuevo System.Net.Sockets.TcpListener, almacenado como $l. Ese objeto se encapsula en parens y se llama inmediatamente .Start()para que abra activamente el socket.

Al ingresar a un forbucle infinito , configuramos nuestro oyente$l para que bloquee con AcceptTcpClient()lo que esperará una conexión. Una referencia a esa conexión (una vez que se realiza) se almacena $c, se encapsula en parens e inmediatamente se llama GetStream()para obtener el flujo de datos. Ese flujo de datos se pasa a un nuevo System.IO.StreamWriterconstructor $w, para que podamos manipularlo. Ese constructor se encapsula en parens y se llama de inmediato Write(...).

Dentro de la Write(...)llamada, tomamos el identificador de nuestro cliente $cy obtenemosRemoteEndPoint propiedad . Esta es la única forma (que he encontrado hasta ahora) de obtener la dirección IP remota. A continuación, debemos volver a emitir eso como un [System.Net.IPEndPoint]objeto para que esté formateado correctamente, encapsularlo en parens y extraer solo la .Addresspropiedad. Luego, -replacelos períodos literales con signos más, luego lo canalizamos a Invoke-Expression(similar a eval) para obtener nuestra suma.

Después de la escritura de IO, debemos llamar .Dispose()para asegurarnos de que el flujo de datos se vacíe al cliente y se cierre. El servidor TCP desconecta la conexión del cliente sin previo aviso, por lo que dependiendo del cliente utilizado, puede colgarse por un momento en este punto. Luego continúa a través del forbucle sin cerrar correctamente las conexiones. Esto también significa que pierde memoria y el sistema se maneja como loco, pero eso no nos importa, ¿verdad? Sin embargo, es posible que deba usar el Administrador de tareas para finalizar el proceso cuando haya terminado de ejecutar el servidor. :RE

También solo IPv4, ya que la sumatoria barfs intenta espectacularmente manejar una dirección IPv6, ya :que no es un operador algebraico válido para iexanalizar.

AdmBorkBork
fuente
2
"Fugas de memoria y el sistema se maneja como un loco" ¿Qué, tienes free()después? delete[], ¿tal vez? : P
gato
8
@tac Sí, hay una gran cantidad de .close()y .dispose()métodos que no estamos pidiendo aquí que haría que la gente en la revisión de código para tener un ajuste.
AdmBorkBork
Oh, no es PS GC'd? ¿O el GC realiza el recuento y no el análisis del alcance?
gato
@tac Sí, PowerShell tiene recolección de basura gracias al sistema .NET subyacente. Pero, dependiendo de cómo llame o aproveche este script, puede encontrarse con errores como este que pierden memoria en la tubería. El código anterior tampoco es seguro para subprocesos, por lo que puede encontrarse con problemas de GC con eso, ya que no estamos cerrando explícitamente el socket.
AdmBorkBork
1
En las pruebas no pude hacer que esto funcionara, probablemente debido a problemas con el firewall que no tengo ganas de arreglar, así que no puedo estar seguro, pero ... creo que puedes soltar el "Sistema" de la mayoría, si no de todos los tipos. tienes ahí es decir: [Net.ipaddress]::Anyfunciona.
Matt
7

PHP, 161 (56?)

Esta es mi primera publicación aquí. Espero que esto salga bien :)

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

Sin golf:

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

Esto solo funciona para IPV4

Editar : Acabo de notar que php es compatible con el servidor básico:
decidí mantener el recuento de caracteres original a menos que alguien confirme si se permite lo siguiente :)

test2.php: (posible solución de 56 bytes)

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

Y luego comience el servicio con:

php -S localhost:8080 test2.php

Chrome como cliente captura de pantalla

Edición 2: wget como cliente

$ wget -qO- localhost:8080
128
Mikael
fuente
Sé que las reglas dicen: "El programa o la función lee el entero N de argumentos o stdin", pero ¿está bien si el programa en este caso es php? ¿O el uso de un servidor incorporado en php se considera una escapatoria?
Mikael
¡Bienvenido a Programming Puzzles & Code Golf! Su solución de 161 bytes se ve muy bien. ¿La solución de 56 bytes que mencionaste es la que tienes debajo test2.php? Si es así, creo que tendría que preguntarle al OP si considerarían que ese tipo de incorporado es aceptable para este desafío. Sin embargo, no es una escapatoria.
Alex A.
Yo diría que usar un servidor TCP incorporado sería aceptable, pero en este caso hablamos de un servidor HTTP incorporado . Entonces, la solución de 56 bytes 1) no hace nada si el cliente solo se conecta y no envía nada; 2) envía solo "[Mié Mar 30 10:15:02 2016] 127.0.0.1:47974 Solicitud no válida (solicitud HTTP con formato incorrecto)" sin ejecutar test2.php en caso de que el cliente envíe, por ejemplo, "foo"; 3) envía un conjunto completo de encabezados de respuesta HTTP antes de la respuesta requerida real en caso de que el cliente envíe una solicitud HTTP válida.
manatwork
@Alex A. Gracias y sí, la solución de 56 bytes está bajo test2.php :)
Mikael
@manatwork Tiene razón, pero estaba pensando que el cliente no está claramente especificado en esta tarea. Entonces, ¿está bien usar un navegador o algo más simple como "wget ​​-qO- localhost: 8080" como cliente?
Mikael
7

ir , 359 311

Este es mi primer programa en Go. Me permitió descubrir una cosa: ¡este definitivamente no es un buen lenguaje de golf!

(¡Felicitaciones a @steve que hizo la mayor 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()}}
dieter
fuente
2
¡Pero seguro que es un buen lenguaje para hacer un servidor tcp!
Numeri
1
Extraño, obtengo el resultado 360 cuando me conecto desde 192.168.0.67, en lugar de 427.
Steve
3
Podría nombrar los paquetes strings + strconv para guardar algunos bytes. Por ejemplo, se "strings"convierte en s "strings"lo que más tarde se strings.Splitvuelve justo s.Split.
Steve
1
Pocos bytes más se eliminaron de pastebin.com/HY84sazE - comenzando a parecer un poco más "golfista" ahora
steve
2
Si usa import(."pkgname")todas las funciones, se importarán al espacio de nombres actual, entonces puede soltar el prefijo. p.ej. import ."fmt"; Println("foo") Si usa Sscanfel fmtpaquete para analizar la dirección en lugar de regex, le ahorrará otros pocos bytes, lo que le dará la ventaja adicional de tener Fprintlnque devolver el total en lugar de importar strconv.
Kristoffer Sall-Storgaard
7

Lisp común, 110 bytes

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

Detalles

(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                     
                 )))
volcado de memoria
fuente
2
¡Yay para Lithp común!
gato
6

q, 88 bytes

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: Toma el segundo argumento de línea de comandos (el primero "-" es para decirle que qno interprete Ncomo un script / archivo) y abre un puerto ( "p ") con él.
    • Nota: llamando q -p N configuran el puerto de forma Nautomática, pero como la pregunta parece sugerir que Ndebería ser un argumento para el programa en lugar del ejecutable en sí, he tomado el camino más largo.
  • Dentro de la .z.pgfunción que maneja las solicitudes entrantes, .z.acontiene la dirección IP como un entero de 32 bits.
    • "i"$0x0 vslo divide en sus 'constituyentes' enteros y sumrealiza la suma.
    • Por último, stringel resultado numérico y anexar"\n" para volver al cliente.
  • .z.ph es otra función para las solicitudes HTTP GET, con manejo adicional para convertir la salida de cadena en una respuesta HTTP válida.

Demostración - Servidor:

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)

Demostración - Cliente (de otra qsesión que se ejecuta en 127.0.0.1):

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

Demostración - Cliente (desde curl):

$ curl localhost:1234
128

$
hjk
fuente
6

LiveScript, 107 105 bytes

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

No hay mucho que agregar, solo son cosas básicas de NodeJS. Los puntos de estilo para &1(segundo argumento), <|(tubería F #, similar a $en Haskell) y biop: (+)en LS es como secciones de operador en Haskell: una función binaria al curry (que agrega sus operandos). También un poco sucio: /si se le da una cadena literal a su derecha, se dividirá.

Ven
fuente
5

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}

Sin golf

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

Ejemplo

$ 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.
$
Steve
fuente
¿Estas seguro que esto es correcto? Recibo la suma impresa en la terminal del servidor, no en la del cliente. De todos modos, puede eliminar todos los paréntesis y cambiar s/\./+/gy/./+/.
manatwork
Ahh, mal leído ... lo revisaré en consecuencia e incorporaré tu buena sugerencia.
Steve
1
while(1){…}{…;redo}según el gran consejo del usuario 130144 . Y exceptuando el->send() llamada, todos los demás paréntesis son innecesarios.
manatwork
4

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

Toma el puerto sobre stdin.

Licuadora
fuente
4

NodoJS (ES6), 129 118 107 bytes

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

Funciona para IPv4. Correr comonode server.js <port>

Mwr247
fuente
En realidad no funciona si el servidor está usando IPv6 (como, por ejemplo, el mío lo hace automáticamente), ya c.remoteAddressque entonces lo sería ::ffff:127.0.0.1. (Probé en el Nodo v5.9.1).
Frxstrem
Además, no tiene una nueva línea final, lo que debería aumentar su puntaje en 2 bytes.
Frxstrem
@Frxstrem Whoops, olvidé esa nueva línea. Sin embargo, solo agrega 1 byte gracias a las cadenas de plantilla. Con respecto a la familia IP:.listen() solía ser el valor predeterminado de IPv4 primero, pero parece que, por error o diseño, esto ha cambiado. El envío seguirá funcionando correctamente en las versiones más nuevas del nodo cuando IPv6 esté desactivado en la máquina host.
Mwr247
4

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

Probablemente se pueda jugar más, no estoy completamente satisfecho con la forma en que tengo que analizar la dirección IP, por ejemplo, parece un truco horrible.

Escucha IPv4 en el puerto dado como argumento.

Kristoffer Sall-Storgaard
fuente
4

PowerShell, 208 206 192 152 bytes

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

información de versión:

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

¡Gracias a TimmyD por salvarme 14 bytes!

Muchas gracias a TessellatingHeckler por salvarme 40 bytes

Nacht
fuente
@TimmyD ah, vaya, me perdí que eso era necesario ... solucionado ahora
Nacht
Una de las formas en que los programas pueden recibir información es desde stdin. Supongo que esta pregunta en particular no especifica eso como permitido, pero es una cuestión general de golf de código que creo que debería contar para PowerShell. Desafortunadamente, es diferente de bash en que no espera la entrada en stdin si no se ha proporcionado ninguno.
Nacht
lo suficientemente justo. arreglado de nuevo
Nacht
Muy bien, ahora para algunos campos de golf - intente lo siguiente en 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
Creo que puede reducir esto a 152: soltar un nuevo objeto y emitir directamente, omitir la conversión de la matriz de bytes y realizar una conversión de cadena de manera diferente, no almacenar $ x en absoluto y soltar los parámetros restantes para enviar (), y se convierte ($t=[net.sockets.tcplistener]$args[0]).start();for(){($z=$t.acceptsocket()).send([char[]]"$($z.remoteendpoint.address-replace"\.","+"|iex)");$z.close()}, lo que solo he probado rápidamente con la conexión netcat, pero parece funcionar de la misma manera, conectarse desde localhost de todos modos.
TessellatingHeckler
4

Código de máquina 8086 (DOS de 16 bits), 163156148148142 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

Código de ensamblaje 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

Esto supone que ntcpdrvse carga en INT 0x61(y cualquier controlador de paquete adecuado en0x60 ). Compilar confasm tcpserv.asm .

Sin embargo, tiene algunos problemas:

  • No comprueba si el argumento es un número de puerto válido o si es siquiera un número.
  • El cliente debe enviar al menos un byte, ya que parece que no puedo encontrar otra forma de saber si un cliente se ha conectado.
  • Solo funciona una vez y se cuelga en un segundo intento. Funciona nuevamente después de un reinicio.
  • El valor devuelto se rellena con ceros a la izquierda.
  • Esta es mi primera entrada de código de golf, y también mi primer programa asm 8086. Estoy seguro de que hay formas de mejorar esto aún más.
usuario5434231
fuente
1
Puede publicar un volcado hexadecimal de la salida compilada para 148 bytes
cat
eso está permitido? Haría esta entrada un poco más competitiva ...
user5434231
1
Muy bien, he cambiado la entrada al código de máquina. También recorté algunos bytes más usando en xor r,rlugar de mov r,0.
user5434231
1
Lo escribí en una máquina dos donde están las nuevas líneas CR LF, así que simplemente fui con eso. De cualquier manera, no tiene sentido contar el tamaño de asm ahora, también podría limpiarlo un poco y agregar algunos comentarios.
user5434231
1
Se supone que eso también sucederá aquí, y funciona; int 0x61devuelve un puerto local aleatorio en ax. Pero también cambia la IP de escucha a algún número de basura ( 4.2.0.0iirc)
user5434231
3

Haskell, 216 bytes

Usando el paquete "network-simple" ( cabal install network-simple). Necesita un par de extensiones de lenguaje ( -XOverloadedStrings -XNoMonomorphismRestriction) para funcionar.

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)

Hay un par de posibles simplificaciones, que incluyen cambiar la wfunción para devolver la suma directamente en lugar de una lista, y usar una función en lugar de un programa para que el número de puerto se pueda especificar como argumento. Sin embargo, no imagino que esto reduciría mucho el tamaño. ¿20 bytes tal vez?

Jules
fuente
¡Agradable! Estoy bastante seguro de que aún puede eliminar algunos bytes cambiando el nombre wa #, así quew h n se h#nahorra 2 bytes por uso.
Actorclavilis
3

Paperas, 114 115 Bytes

Golfizado:

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}

Sin golf:

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

Esta es la versión de InterSystems Caché de Mumps, si hay una versión que puede adquirir la dirección TCP más corta que ##class(%SYSTEM.TCPDevice).PeerAddr() (ya que es casi un 1/3 del programa completo) , podría tener una mejor oportunidad contra algunos de los otros idiomas publicados ya ... ;-)

Editar: Gracias a @TimmyD: me perdí la lectura del puerto de STDIN o los argumentos en lugar de estar codificado. Editado; agregó 1 byte al programa.

zmerch
fuente
@TimmyD - Ah, tienes razón. Perdí eso al leer los requisitos. Editará posthaste.
zmerch
3

C, 535 bytes

Bueno, alguien tuvo que hacer esto.

Agregué un solo salto de línea para que el código publicado tenga 536 caracteres.

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

compilar con gcc [file_name] -o server

corre con ./server [port]

conectar con telnet localhost [port]

No sé
fuente
3
¡Buena respuesta! Como se mencionó anteriormente , puede guardar algunos bytes utilizando valores reales para algunas constantes, como AF_INET y SOCK_STREAM.
Hannes Karppila
2

Java, 210 bytes

Golfizado:

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

Expandido:

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

Esta es una reunión de todos los consejos que di en otras respuestas de Java, más la escritura como una función en lugar de un programa completo, que gana aproximadamente 70 bytes en comparación con el programa.

Olivier Grégoire
fuente
2

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)

Lamentablemente, tuve que usar Network.Socketpara obtener acceso a la dirección IP remota como un entero en lugar de una cadena. Hubiera salvado docenas de caracteres si pudiera hacerlo s <- listenOn (PortNumber n), en lugar de tener que llamar explícitamente socket, binde listenindividualmente. Pero, lamentablemente, Network.acceptme da una cadena de host , no un entero de dirección IP , así que tuve que recurrir aNetwork.Socket.accept amigos.

La función ftoma un número de puerto como argumento y crea un socket de servidor ( s) que escucha en ese puerto. Luego llama a la función gcon el socket del servidor. gbucles para siempre, aceptando conexiones. La función btoma una dirección IPv4 real y calcula la suma de sus dígitos.

Estoy seguro de que alguien en algún lugar puede hacerlo mejor que yo. Quería mostrar cuán malditas son las cosas de socket fáciles en Haskell ... pero luego fallé miserablemente, porque necesito acceso a la dirección IP, que generalmente no es fácil de obtener.

Orquídea matemática
fuente
El paquete "simple de red" proporciona una interfaz mucho más agradable que pasa el SockAddr a una función que usted le brinda, lo que facilita las cosas. Vea mi solución que estoy a punto de publicar ...
Jules
Son evidentes algunas simplificaciones: (1) Creo que withSocketsDosolo es necesario en Windows, por lo que si se ejecuta en Linux puede ignorarse; (2) 0xFF es un personaje más largo que 255; (3) convertir el zócalo en un mango y usar IO regular es mucho más largo que usarlo Network.Socket.send. Sí, sendestá en desuso, pero el motivo no es relevante para este escenario (solo se relaciona con texto o datos binarios que no son ASCII), por lo que parece razonable usarlo.
Jules
Network.accept gives me a host string, not an IP address integer¿No puedes dividir la cadena de IP en el ".", mapde Haskell función cadena-a-serie sobre la cadena de dividir y sumar los resultados?
gato
2

Lua 169 162 160 153 151 148 138 129 bytes

Versión de golf

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

Requiere la instalación de Luasocket y un intérprete que admita etiquetas. Lo probé con Luajit y también puedo confirmar que el código no funciona con Lua 5.1.

Versión sin golf

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

Editar 1:

Cambiado i=({c:getpeername()})[1]a soloi=c:getpeername()

Edición 2:

Se eliminaron las llaves de la instrucción require.

Edición 3:

Se eliminaron las llaves alrededor del vararg, disminuyó un poco el recuento de bytes.

Edición 4:

Se eliminó el paréntesis alrededor de "% d +", más corto en 2 bytes.

Editar 5:

Se eliminó la variable innecesaria i.

Editar 6:

Cambió la ip de "127.0.0.1" a 0. (Gracias a xyzzy en #lua)

Editar 7:

Se eliminó la llamada de función a tonumber ya que las cadenas se convierten en números automáticamente (Gracias a Trebuchette por la sugerencia, no lo sabía)

Seeseemelk
fuente
1
Solo Lua 5.2 y más etiquetas de soporte, si tiene curiosidad
Trebuchette
1
Además, Lua automáticamente convierte cadenas a números con el +operador, para que pueda sacar tonumber.
Trebuchette
2

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)

Toma el número de puerto como una línea en stdin; requiere network-simplede Cabal.

Como es habitual con las respuestas de Haskell que no se limitan a funciones puras, importsocupan demasiados bytes. La nueva línea final también vale 9 bytes ...

Algo similar a la respuesta de @ Jules, pero uso manipulación de cadenas en lugar de operaciones de bytes. I estola usado la -XOverloadedStringsextensión, así, que es probablemente un valor de 19 bytes extra.

Actorclavilis
fuente
2

C, 243188 bytes (o quizás 217162 bytes)

V2: ver abajo las explicaciones.

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

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

Probablemente más golf posible mañana por la mañana. Arreglaré esta publicación después de esas actualizaciones.


V1:

Este fue realmente muy divertido para el 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);}}

Funciona para IPv4. Principalmente es una implementación sencilla. Los tres componentes principales son

Crear el zócalo:

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

Utilizamos las diversas formas explícitas de las constantes AF_INET, etc., y hacemos uso del hecho de que cuando una estructura se inicializa en C de esta manera, los elementos no especificados se ponen a cero.

Escuche a los clientes, acéptelos y cierre sus conexiones:

para (escuchar (s, 8); c = aceptar (s, & C, & g); q = fclose (g))

Finalmente para enviar a cada cliente los datos:

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

La IP se almacena C.sin_addr.s_addrcomo un entero de 32 bits donde cada octeto está representado por uno de los cuatro bytes. Sumamos estos bytes con el bucle for y luego los imprimimos en la secuencia usando fprintf.

Tengo una solución de 217 bytes más corta, pero no estoy completamente seguro de que no viole las lagunas estándar, ya que requiere que el puerto se dé en unario en orden de bytes de red como argumentos de línea de comandos. Es decir, para ejecutar el servidor en el puerto 12345 habría que llamar

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

donde el número total de 1s es 14640. Por decir lo menos es un poco ... engorroso. Pero aquí está de todos modos:

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

Raqueta, 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)))

Sin golf:

#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)))
gato
fuente
2

Factor, 155 146 131 206 190 bytes

Bueno, acabo de aprender mucho sobre la programación de sockets de bajo nivel. No creo que quiera volver a hacerlo porque me duele la cabeza.

[ 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í, roscado, y no regresa, correcto.

gato
fuente
¿Se puede usar en 10 base>lugar de string>number?
fede s.
@fedes. Wow, nunca supe que existía. ¡Creo que eso me permitirá acortar muchas de mis respuestas de Factor!
gato
Y 10 >basepara número> cadena, también.
fede s.
1
@fedes. Esos merecen una respuesta aquí : D
gato