Um servidor TCP simples

104

Escreva um programa ou função que escute o tráfego TCP de entrada na porta N. Ele oferece um serviço simples: calcula a soma dos campos de endereço IP da conexão e retornos de entrada.

Programa ou função lê N inteiro a partir de argumentos ou stdin. Ele escuta as conexões TCP de entrada na porta N. Quando alguém se conecta a essa porta, o programa calcula a soma de seus campos de endereço IP e o envia de volta ao cliente com nova linha final e fecha a conexão.

  • O número da porta N é uma porta válida e 2 10 <N <2 15
  • A nova linha à direita pode ser \nou\r\n
  • Você pode usar IPv4 ou IPv6. Como os endereços IPv6 são gravados em formato hexadecimal, você também deve fornecer o resultado no mesmo formato, por exemplo 2001:0db8:0000:0042:0000:8a2e:0370:7334 => 12ecd.

Isso é . Aplicam-se regras e brechas padrão.

Exemplo

Você executa seu servidor com ./server 1234. O servidor está agora em execução e aguardando conexões na porta 1234. Em seguida, um cliente se 127.0.0.1conecta ao seu servidor. O servidor executa um cálculo simples: 127+0+0+1 => 128e envia o resultado para o cliente (com caractere de nova linha): 128\n. Em seguida, o servidor fecha a conexão e aguarda o próximo cliente.

Entre os melhores

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
fonte
1
É permitido usar o inetd / xinetd ou similar?
Digital Trauma
91
Eu gosto disso, já que é um desafio para o golfe que é improvável que as línguas sejam muito boas.
Isaacg 28/03
9
Não é apenas surpreendente que um servidor TCP seja aparentemente um programa muito fácil de escrever, mas estou profundamente impressionado com o fato de estar sendo jogado por diversão. Voltarei a lutar com o FizzBuzz como um imbecil.
MonkeyZeus 29/03
17
@isaacg É só o tempo antes que alguém encontra o servidor TCP embutido no Mathematica
Downgoat
3
@MonkeyZeus Para ser justo, você não verá nenhum bom servidor TCP aqui. Tornar um servidor TCP escalável e confiável, que lida com todos os meandros do TCP (e do protocolo de aplicativos), é um pouco mais difícil: D Embora certamente ajude que o protocolo seja extremamente simples - você nem precisa ler o fluxo, algo que eu vi quebrado em muitos servidores TCP para contar: D
Luaan 30/03/16

Respostas:

57

Bash + netcat + ss +…, 65 60 caracteres

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

Não é uma solução séria, estava apenas curioso sobre essa possibilidade.

Graças a:

  • ninjalj por sugerir a awkfiltragem com base (-5 caracteres)

Exemplo de execução:

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

No Ubuntu, você pode obter ncdo netcat-traditional (não, o netcat-openbsd não é bom) e ssdo iproute2 .

homem a trabalhar
fonte
22
Por que você diz que não é uma solução séria? Desde que funcione conforme o esperado, não vejo razão para que isso não deva ser considerado sério. Também é o menor por uma margem bastante significativa no momento.
Alex A.
A maior preocupação contra isso apareceu durante a discussão com o @JesseSielaff quando soube que em sistemas com IPv6 configurado, as informações relacionadas ao soquete podem ser formatadas de maneira diferente. Não possui esse sistema para testá-lo. Pelo qual estou pensando se seria mais correto transformá-lo em CW.
28816 manatwork
3
Meu entendimento das especificações é que você precisa oferecer suporte a IPv4 ou IPv6, não a ambos. Portanto, desde que funcione para o IPv4, não oferecer suporte ao IPv6 não deve importar, eu acho.
Alex A.
1
@AlexA. Pelo menos eu acho que minha pergunta diz isso. Devo esclarecer isso?
Hannes Karppila 29/03
@HannesKarppila, sua pergunta é clara. O possível problema é que minha solução pode exigir que o sistema operacional seja configurado de uma maneira específica para poder executar. Por isso, estou preocupado porque pode falhar se o IPv6 estiver configurado, independentemente de eu lidar com isso ou não. Alguém que tenha IPv6 configurado poderia dizer que com certeza ...
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]);}}}

Exemplo clássico de um servidor C # TCP básico. Testando:

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.

Raposa de fogo:

LegionMammal978
fonte
7
Você pode salvar 1 Byte usando em int Mainvez de void Main. Como o programa nunca retorna, o compilador não requer uma returndeclaração.
raznagul
E não, não vaza. Na verdade, é bastante determinista sobre a liberação de recursos também. Além disso, o argumento para Starté opcional, salvando outro caractere.
Luaan 30/03/16
@Lanan Sim, isso foi deixado de depurar.
precisa
Além disso, você pode usar usingno TcpClient, que salvará mais três caracteres (use o {}de for) e, fazendo o mesmo com o StreamWritersalvará mais um.
Luaan 30/03/16
@ Luan eu preciso explicitamente Flusho StreamWriterpara fazê-lo funcionar corretamente.
LegionMammal978 30/03
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

Inclui um cabeçalho ELF de 52 bytes, um cabeçalho de programa de 32 bytes, 111 bytes de código de programa + 3 bytes de código para pular dentro dos cabeçalhos.

Informações sobre como criar pequenas executáveis ELF pode ser encontrada em breadbox 's ' A Whirlwind tutorial sobre como criar Realmente Teensy ELF executáveis para Linux ' .

O Linux / i386 usa a socketcall(2)chamada de sistema multiplex, que recebe ebxa chamada de soquete específica (as SYS_*macros de /usr/include/linux/net.h) e ecxum ponteiro para a área de argumento da chamada de biblioteca original.

Algumas coisas feitas para manter o executável pequeno:

  • Ele assume que os registros são zerados na entrada, o que o Linux faz, mas não é exigido pelo padrão ELF (o único requisito é que, nos EDXpontos de entrada, uma função de finalização (útil para executáveis ​​carregados pelo vinculador dinâmico) ou seja NULL).
  • Ele assume na inicialização (normalmente por um shell) os únicos descritores de arquivos abertos são 0, 1 e 2. O que significa que o soquete de escuta será fd 3 e o soquete aceito será fd 4.
  • Ele assume que existem exatamente 2 argumentos (incluindo argv[0]).
  • O mesmo espaço de pilha é reutilizado para as chamadas para bind(2), listen(2)e accept(2).
  • Para pular os campos phentsizee phnum, um byte é anexado, transformando-se em uma CMPoperação que leva os campos phentsizee phnumcomo imediatos (truque descaradamente roubado da solução da breadbox para o 123 no anarchy golf ).
  • As operações de seqüência de caracteres x86 LODS(carregamento no acumulador e índice de origem de incremento / decremento) e STOS(armazenamento no acumulador e índice de destino de incremento / decréscimo) são boas para o código curto.
  • XCHG EAX, regé de 1 byte, comparado a MOV EAX, reg, que leva 2 bytes.
  • CDQ/CLTD(estender sinal EAXpara EDX:EAX) pode ser usado como uma forma de 1 byte para zerar o EDXregistro.
  • BSWAPé útil para implementar htons().

Nasm fonte:

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
fonte
4
Esta resposta é muito subestimada.
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, posso postar uma resposta do NodeJS! IPv4 somente agora.

Execução da amostra: node script.js 1024. De outro terminal:

$ curl 127.0.0.1:1024
128
nickb
fonte
2
Eu conto 127 bytes agora, embora você possa reduzi-lo a 126 trocando por '\n'uma sequência de modelo que contém uma nova linha literal.
Mwr247
Isso não atenderia aos requisitos porque você está criando um servidor HTTP, quero dizer, tecnicamente é um servidor TCP, mas você não pode simplesmente usar o módulo TCP e salvar um personagem?
MayorMonty
14

Tcl, 92

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

Bastante auto-explicativo:

socket -server s $argv cria um soquete de escuta na porta especificada nos argumentos.

Toda vez que uma nova conexão chega, ela proc sé chamada, com canal, endereço de origem e porta de origem como parâmetros. string mapsubstitutos .para +o endereço de fonte, e expraritmeticamente avalia o resultado, que é, em seguida, putsde volta para o canal de conexão c.

vwait executa um loop de eventos para capturar os eventos de conexão recebidos.


Crédito para @DonalFellows pelo seguinte:

Aqui está uma versão que lida com IPv6 (requer Tcl 8.6; a maior parte do comprimento extra é devido à produção de uma resposta 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
fonte
1
Usar applynão parece salvar nada. Nem você pode usar, tcl::mathop::+ {*}[split $a .]pois é um pouco mais longo. Você também não pode depilar nada com nomes de opções. Mas o suporte ao IPv6 é bastante trivial de se adicionar e custa apenas alguns bytes de código mais (e uma regsubabordagem baseada no mesmo é o mesmo).
Donal Fellows
ahhh, Tcl / Tcl-DP ... incrível monte de ferramentas. (nos anos 90, um professor nos mostrou que poderíamos escrever um Excel distribuído em rede (com uma grade e incluindo avaliação de fórmulas!) compartilhado entre várias pessoas com (iirc) 4 linhas (curtas) para o servidor e 5 para os clientes. ..
Olivier Dulac 31/03
proc s {c a p}você realmente precisa de todo esse espaço em branco?
cat
12

Groovy 133 , 125 , 93 , 89

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

Somente IPv4, provavelmente.

Ungolfed:

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

Testando:

$ telnet localhost 9000
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
128
Connection closed by foreign host.
Will Lp
fonte
1
.toInteger()as inte s.inetAddress.address*.toInteger()(s.inetAddress.address as int[]). E há um espaço extra depois .with.
28816 manatwork
@manatwork thx! Atualizada.
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()

Ativa a porta stdin, apenas IPv4. Funciona no GNU / Linux (e, presumo, na maioria das outras unidades), que expande automaticamente "" para "0.0.0.0", embora não tenha certeza sobre o Windows.

sammko
fonte
2
Você pode salvar vários bytes. Em primeiro lugar, os espaços import *e , SOCK_STREAMsão desnecessários. Além disso, a linha de envio pode ser escrita com mais eficiência como c.send(b"%d\n"%eval(a[0].replace(".","+"))).
Hannes Karppila 28/03
2
@HannesKarppila oh, obrigado. esqueci os espaços, o hack eval é bem legal.
sammko
2
AF_INET e SOCK_STREAM são apenas constantes; AF_INET é 2 e SOCK_STREAM é 1. Além disso, como mencionado, SOCK_STREAM é desnecessário; então você pode reduzi-lo usando s=socket(2).
28516 Skyler #
1
você não pode simplesmente fazer socket () e, portanto, salvar outro byte?
Foon 28/03
1
Você pode economizar 10 caracteres usando Python 2. Em seguida, int(input())torna-se input()ea parte send tornac.send(`eval(a[0].replace(".","+"))`)
Blender
9

Java, 371 368 350 344 333 310 295 282 bytes

Golfe

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

Resultado

mallard@steamroller:~$ telnet localhost 8888
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
128
Connection closed by foreign host.
Matthew Smith
fonte
1
Remova int k=e substitua ok por todas as c coisas Integer.toString(k). Para salvar alguns bytes.
GiantTree 28/03
1
Javas byte quase certeza mexe-se o valor de retorno para 192.168.2.1 ou similar endereços com um byte acima 127.
AlexR
1
Alterar interfacepara classdeve ganhar mais alguns bytes
ortis
2
Use em a.getOutputStream().write((c[0] + c[1] + c[2] + c[3]+"\n").getBytes());vez denew DataOutputStream(a.getOutputStream()).writeBytes(c[0] + c[1] + c[2] + c[3] + "\n")
ortis 29/03
3
Não é try(Socket a=...){}mais curto que a.close();? Requer Java 7, mas pode ganhar 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()}

Economizei 35 bytes graças a Matt ... Economizei outros 11 bytes por alias New-Objecte pequenos ajustes ... Economizei mais 30 bytes usando implicitamente o host local em vez do anyendereço IP e corrigido para levar em conta o uso contínuo conforme especificado originalmente e perdi

Realmente semelhante à resposta do C # , já que o .NET está subjacente a ambos. Economizamos alguns bytes aqui na resposta em C #, aproveitando a funcionalidade de retorno do PowerShell (envolvendo nossa declaração / atribuição em parens e, em seguida, chamando imediatamente os métodos.), Mas perdemos muito por precisar formular a soma. . O fato de termos nomes / chamadas de classe um pouco mais curtos é o motivo pelo qual essa resposta está superando o C #.

Explicação

Primeiro, criamos um New-Alias(com o nalalias) para economizar ao digitar New-Objectmais tarde. O restante da primeira linha está configurando um Ouvinte TCP. Passamos a linha de comando $args[0]como entrada para criar um novo System.Net.Sockets.TcpListener, armazenado como $l. Esse objeto é encapsulado em parênteses e imediatamente chamado .Start()para que ele abra ativamente o soquete.

Entrando em um forloop infinito , configuramos nosso ouvinte $lpara bloquear com o AcceptTcpClient()qual aguardará uma conexão. Uma referência a essa conexão (uma vez feita) é armazenada $c, encapsulada em parênteses e imediatamente chamada GetStream()para obter o fluxo de dados. Esse fluxo de dados é passado para um novo System.IO.StreamWriterconstrutor $w, para que possamos manipulá-lo. Esse construtor é encapsulado em parens e imediatamente chamado Write(...).

Dentro da Write(...)chamada, pegamos nosso identificador de cliente $ce obtemos a RemoteEndPointpropriedade do cliente . Esta é a única maneira (que eu encontrei até agora) de obter o endereço IP remoto. Em seguida, precisamos refazê-lo como um [System.Net.IPEndPoint]objeto para que ele seja formatado corretamente, encapsule isso em parens e puxe apenas a .Addresspropriedade. Em seguida, -replaceos períodos literais com sinais de adição e o canalizamos Invoke-Expression(semelhante a eval) para obter nosso somatório.

Após a gravação do IO, precisamos ligar .Dispose()para garantir que o fluxo de dados seja liberado para o cliente e fechado. O servidor TCP interrompe a conexão do cliente sem aviso; portanto, dependendo do cliente usado, ele pode travar um pouco nesse momento. Em seguida, continua o forloop sem fechar corretamente as conexões. Isso também significa que vaza memória e o sistema lida como um louco, mas não nos importamos com isso, certo? Você pode precisar usar o Gerenciador de Tarefas para interromper o processo quando terminar de executar o servidor. : D

Também apenas IPv4, pois o somatório vomita tentando manipular um endereço IPv6 espetacularmente, já que :não é um operador algébrico válido iexpara analisar.

AdmBorkBork
fonte
2
"Vazamento de memória e sistema lida como um louco" O que você tem com free()eles depois? delete[], talvez? : P
cat
8
@tac Sim, existem vários métodos .close()e .dispose()métodos que não estamos chamando aqui que causariam problemas às pessoas na Code Review.
28416 AdmBorkBork
Oh, o PS GC não é? Ou o GC faz recontagem e não analisa o escopo?
cat
@tac Sim, o PowerShell tem coleta de lixo graças ao sistema .NET subjacente. Mas, dependendo de como você está chamando ou alavancando esse script, você pode encontrar bugs como esse que estão vazando memória no pipeline. O código acima também não é seguro para threads e, portanto, pode ter problemas com o GC, pois não estamos fechando explicitamente o soquete.
28416 AdmBorkBork
1
Nos testes, não consegui fazer isso funcionar, provavelmente devido a problemas de firewall que não me parecem consertar, por isso não posso ter certeza, mas ... Acho que você pode eliminar o "Sistema" da maioria, se não de todo o tipo você tem aí ie: [Net.ipaddress]::Anyfunciona.
Matt
7

PHP, 161 (56?)

Este é o meu primeiro post aqui. Espero que isso dê certo :)

<?php $s=socket_create_listen($argv[1]);while($c=socket_accept($s)){socket_getpeername($c,$r);socket_write($c,array_sum(explode('.',$r))."\n");socket_close($c);}

Ungolfed:

<?php 
    $s = socket_create_listen($argv[1]); //Create socket
    while( $c = socket_accept($s) ) { // Loop accepting new connections
        socket_getpeername($c, $r); // Get IP address in $r
        socket_write($c, array_sum(explode('.', $r))."\n"); //Calculate sum
        socket_close($c); //Close connection and wait for next one
    }

Terminal:

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

Isso funciona apenas para IPV4

Edit : Acabei de notar que o php suporta servidor básico:
Decidi manter a contagem de caracteres original, a menos que alguém confirme se o seguinte é permitido :)

test2.php: (possível solução de 56 bytes)

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

E, em seguida, inicie o serviço com:

php -S localhost:8080 test2.php

Chrome como cliente captura de tela

Editar 2: wget como cliente

$ wget -qO- localhost:8080
128
Mikael
fonte
Eu sei que as regras dizem: "Programa ou função lê o número N inteiro de argumentos ou stdin", mas tudo bem se o programa nesse caso for o próprio php? Ou o uso do servidor embutido no php é considerado uma brecha?
Mikael
Bem-vindo à programação de quebra-cabeças e código de golfe! Sua solução de 161 bytes está ótima. A solução de 56 bytes que você mencionou abaixo test2.php? Nesse caso, acho que você teria que perguntar ao OP se eles considerariam esse tipo de built-in aceitável para esse desafio. Não é uma brecha.
Alex A.
Eu diria que o uso de um servidor TCP embutido seria aceitável, mas nesse caso falamos sobre um servidor HTTP embutido . Portanto, a solução de 56 bytes 1) não faz nada se o cliente apenas conectar e enviar nada; 2) envia apenas de volta “[Wed Mar 30 10:15:02 2016] 127.0.0.1:47974 Solicitação inválida (solicitação HTTP malformada)” sem executar o test2.php, caso o cliente envie por exemplo “foo”; 3) envia um conjunto completo de cabeçalhos de resposta HTTP antes da resposta real necessária, caso o cliente envie uma solicitação HTTP válida.
Manatwork 30/03/16
@Alex A. Obrigado e sim, solução de 56-byte está sob test2.php :)
Mikael
@ manatwork Você está correto, mas eu estava pensando que o cliente não está claramente especificado nesta tarefa. Então, está tudo bem em usar o navegador ou algo ainda mais simples como "wget ​​-qO- localhost: 8080" como cliente?
Mikael
7

Go , 359 311

Este é o meu primeiro programa no Go - ele me permitiu descobrir uma coisa: esta definitivamente não é uma boa linguagem para o golfe!

(Parabéns a @steve, que fez a maior parte do golfe!)

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
fonte
2
Mas com certeza é uma linguagem agradável para criar um servidor tcp!
Numeri
1
Estranho, estou recebendo o resultado 360 quando eu ligar a partir de 192.168.0.67, ao invés de 427.
steve
3
Você pode nomear os pacotes strings + strconv para economizar alguns bytes. por exemplo, "strings"torna s "strings"- se para que o posterior strings.Splitse torne justo s.Split.
steve
1
Poucos mais bytes foram removidos de pastebin.com/HY84sazE - começando a parecer um pouco mais "golfe" agora
steve
2
Se você usar import(."pkgname")todas as funções serão importadas para o espaço para nome atual, poderá soltar o prefixo. por exemplo. import ."fmt"; Println("foo") Se você usar Sscanfo fmtpacote para analisar o endereço em vez de regex, você economizará mais alguns bytes, oferecendo o bônus de Fprintlndevolver o total em vez de importar strconv.
Kristoffer Sall-Storgaard 31/03
7

Lisp comum, 110 bytes

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

Detalhes

(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                     
                 )))
coredump
fonte
2
Yay para Lithp comum!
cat
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: Pega o segundo argumento da linha de comando (o primeiro "-"é para dizer para qnão interpretar Ncomo um script / arquivo) e abre uma porta ( "p ") com ele.
    • Nota: A chamada q -p Ndefine a porta como Nautomática, mas, como a pergunta parece sugerir que Ndeveria ser um argumento para o programa, e não para o executável, eu já percorri o caminho mais longo.
  • Dentro da .z.pgfunção que lida com solicitações recebidas, .z.amantém o endereço IP como um número inteiro de 32 bits.
    • "i"$0x0 vsdivide-o em seu número inteiro 'constituintes' e sumfaz a soma.
    • Por último, stringo resultado numérico e anexado "\n"a ele para retornar ao cliente.
  • .z.ph é outra função para solicitações HTTP GET, com manipulação extra para converter a saída da string em uma resposta HTTP válida.

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

Demo - Cliente (de outra qsessão em execução 127.0.0.1):

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

Demonstração - Cliente (de curl):

$ curl localhost:1234
128

$
hjk
fonte
6

LiveScript, 107 105 bytes

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

Nada a acrescentar, são apenas coisas básicas do NodeJS. Os pontos de estilo para &1(segundo argumento), <|(tubulação F #, semelhante a $Haskell) e biop: (+)no LS são como seções do operador em Haskell: uma função binária com curry (que adiciona seus operandos). Também um pouco sujo: /se for dada uma string literal à sua direita, será dividida.

Ven
fonte
5

Perl, 141 132 + 1 = 133 bytes

Golfe

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

Exemplo

$ 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
fonte
Tem certeza de que isso está correto? Recebo a soma impressa no terminal do servidor, não na do cliente. De qualquer forma, você pode remover todos os parênteses e alterar s/\./+/gy/./+/.
manatwork
Ahh, mal interpretado ... revisará de acordo e incorporará sua boa sugestão.
steve
1
while(1){…}→ de {…;redo}acordo com a ótima dica do usuário130144 . E, exceto a chamada, todos os outros parênteses são desnecessários. ->send()
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()

Assume o porto sobre stdin.

Liquidificador
fonte
4

NodeJS (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
fonte
Na verdade, não funciona se o servidor estiver usando IPv6 (como, por exemplo, o meu funciona automaticamente), pois c.remoteAddressseria então ::ffff:127.0.0.1. (Eu testei no nó v5.9.1).
Frxstrem 29/03
Além disso, você não tem uma nova linha à direita, o que deve aumentar sua pontuação em 2 bytes.
Frxstrem
@Frxstrem Opa, esqueci essa nova linha. Apenas adiciona 1 byte, graças às seqüências de caracteres do modelo. Em relação à família de IP: .listen()usado como padrão no IPv4 primeiro, mas parece que por bug ou design isso mudou. O envio ainda funcionará corretamente nas versões mais recentes do nó quando o IPv6 estiver desativado na máquina host.
Mwr247
4

Vá, 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()}}

Provavelmente pode ser jogado mais longe, não estou totalmente satisfeito com a maneira como tenho que analisar o endereço IP, por exemplo, parece um hack horrível.

Escuta no IPv4 na porta fornecida como argumento.

Kristoffer Sall-Storgaard
fonte
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()}

versão informação:

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

Obrigado ao TimmyD por me salvar 14 bytes!

Agradecimentos massivos ao TessellatingHeckler por me salvar 40 bytes

Nacht
fonte
@TimmyD ah oops eu perdi que o que era necessário ... corrigido agora
Nacht
Uma das maneiras pelas quais os programas podem receber informações é do stdin. Suponho que essa pergunta em particular não especifique isso como permitido, mas é uma coisa geral de código-golfe que acho que deve contar para o PowerShell. Infelizmente, é diferente do bash, pois não espera pela entrada no stdin se nenhuma foi fornecida.
Nacht
justo. fixo novamente
Nacht
Tudo bem, agora para alguns jogadores de golfe - tente o seguinte em 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 31/03
1
Eu acho que você pode derrubar isso em 152 - soltar novo objeto e converter diretamente, pular a conversão da matriz de bytes e fazer uma string de forma diferente, não armazenar $ x e soltar os parâmetros restantes para send (), e torna ($t=[net.sockets.tcplistener]$args[0]).start();for(){($z=$t.acceptsocket()).send([char[]]"$($z.remoteendpoint.address-replace"\.","+"|iex)");$z.close()}- se - que eu só testei rapidamente com a conexão netcat, mas parece funcionar da mesma maneira - conectando a partir do localhost de qualquer maneira.
TessellatingHeckler
4

Código de máquina 8086 (DOS de 16 bits), 163 156 148 148 142 bytes

00000000  31 c0 bb 0a 00 31 c9 be  81 00 bf 80 00 8a 0d 01  |1....1..........|
00000010  cf 46 8a 0c 80 e9 30 f7  e3 00 c8 39 fe 72 f2 89  |.F....0....9.r..|
00000020  c3 89 c1 b8 01 10 ba ff  ff 31 f6 31 ff cd 61 53  |.........1.1..aS|
00000030  b8 00 12 bf 80 00 b9 01  00 ba ff ff cd 61 b8 00  |.............a..|
00000040  14 cd 61 31 c0 bb 0a 00  83 c7 06 8d 4d 04 26 02  |..a1........M.&.|
00000050  05 80 d4 00 47 39 cf 72  f5 bf 84 00 b9 80 00 bb  |....G9.r........|
00000060  0a 00 4f 31 d2 f7 f3 80  c2 30 88 15 39 cf 77 f2  |..O1.....0..9.w.|
00000070  1e 07 b8 0e 13 5b bf 80  00 b9 04 00 ba ff ff cd  |.....[..........|
00000080  61 b8 00 11 ba 01 00 cd  61 b8 00 4c cd 21        |a.......a..L.!|
0000008e

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

Isso pressupõe que ntcpdrvestá carregado em INT 0x61(e qualquer driver de pacote adequado em 0x60). Compile com fasm tcpserv.asm.

No entanto, existem alguns problemas:

  • Ele não verifica se o argumento é um número de porta válido ou se é mesmo um número.
  • O cliente deve enviar pelo menos um byte, pois não consigo encontrar outra maneira de saber se um cliente está conectado.
  • Funciona apenas uma vez e trava em uma segunda tentativa. Funciona novamente após uma reinicialização.
  • O valor retornado é preenchido à esquerda com zeros.
  • Esta é minha primeira entrada de código de golfe e também meu primeiro programa 8086 asm. Tenho certeza de que existem maneiras de melhorar isso ainda mais.
user5434231
fonte
1
Você pode apenas postar uma hexdump da saída compilada para 148 bytes
gato
Isso é permitido? Não faria esta entrada um pouco mais competitivo ...
user5434231
1
Tudo bem, eu mudei a entrada para o código da máquina. Também raspou mais alguns bytes usando em xor r,rvez de mov r,0.
user5434231
1
Eu escrevi em uma máquina dos onde estão as novas linhas CR LF, então eu apenas fui com isso. De qualquer maneira, é inútil contar o tamanho do ASM agora, é melhor limpá-lo um pouco e adicionar alguns comentários.
user5434231
1
Isso deveria acontecer aqui também, e funciona; int 0x61retorna uma porta local aleatória em ax. Mas também muda o IP escuta para algum número de lixo ( 4.2.0.0IIRC)
user5434231
3

Haskell, 216 bytes

Usando o pacote "simples de rede" ( cabal install network-simple). Precisa de algumas extensões de idioma ( -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)

Existem algumas simplificações possíveis, incluindo alterar a wfunção para retornar a soma diretamente em vez de uma lista e usar uma função em vez de um programa para que o número da porta possa ser especificado como argumento. Eu não imagino que isso reduziria muito o tamanho, no entanto. 20 bytes, talvez?

Jules
fonte
Agradável! Certeza que você ainda pode raspar alguns bytes off renomeando wpara #, então w h ntorna-se h#npara uma economia de 2 bytes por uso.
precisa saber é o seguinte
3

Caxumba, 114 115 Bytes

Golfe:

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

Esta é a versão do Mumps da InterSystems Caché - se houver uma versão por aí que possa adquirir o endereço TCP mais curto que ##class(%SYSTEM.TCPDevice).PeerAddr() (já que é quase um 1/3 de todo o programa) , poderá ter uma chance melhor contra alguns dos outros idiomas já publicados ... ;-)

Edit: Graças a @ TimmyD - perdi a leitura da porta do STDIN ou argumentos em vez de ser codificado. Editado; adicionou 1 byte ao programa.

zmerch
fonte
@ TimmyD - Ah, você está correto. Perdeu isso ao ler os requisitos. Editará o pós-restauração.
Zmerch #
3

C, 535 bytes

Bem, alguém tinha que fazer isso.

Eu adicionei uma quebra de linha única para que o código postado tenha 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;}

ajuntar com gcc [file_name] -o server

correr com ./server [port]

Conectar com telnet localhost [port]

Não sei
fonte
3
Boa resposta! Como mencionado anteriormente , você pode salvar alguns bytes usando valores reais para algumas constantes, como AF_INET e SOCK_STREAM.
Hannes Karppila
2

Java, 210 bytes

Golfe:

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 é uma reunião de todas as dicas que eu dei em outras respostas Java, além da escrita como uma função em vez de um programa completo, que ganha aproximadamente 70 bytes em comparação com o programa.

Olivier Grégoire
fonte
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)

Infelizmente, eu tive que usar Network.Socketpara obter acesso ao endereço IP remoto como um número inteiro e não como uma string. Teria economizado dezenas de caracteres se eu pudesse s <- listenOn (PortNumber n), ao invés de ter que ligar explicitamente socket, binde listenindividualmente. Mas, infelizmente, Network.acceptme fornece uma string de host , não um número inteiro de endereço IP , então tive que recorrer aNetwork.Socket.accept amigos.

A função fusa um número de porta como argumento e cria um soquete de servidor ( s) escutando nessa porta. Em seguida, chama a função gcom o soquete do servidor. glaços para sempre, aceitando conexões. A funçãob pega um endereço IPv4 real e calcula a soma de seus dígitos.

Tenho certeza de que alguém em algum lugar pode fazer isso melhor do que eu. Eu queria mostrar como as coisas de soquetes fáceis estão em Haskell ... mas depois falhei miseravelmente, porque preciso acessar o endereço IP, o que geralmente não é fácil de obter.

MathematicsOrchid
fonte
O pacote "simples de rede" fornece uma interface muito melhor que passa o SockAddr para uma função que você atribui, o que facilita as coisas. Veja minha solução que estou prestes a postar ... #
317 Jules
Algumas simplificações são aparentes: (1) acredito que withSocketsDosó é necessário no Windows; portanto, se estiver sendo executado no Linux, ele poderá ser ignorado; (2) 0xFF é um caractere maior que 255; (3) converter o soquete em um identificador e usar E / S regulares é muito mais demorado do que usar Network.Socket.send. Sim, sendfoi preterido, mas o motivo não é relevante para esse cenário (ele se refere apenas a texto não ASCII ou dados binários), portanto, parece razoável usá-lo.
Jules
Network.accept gives me a host string, not an IP address integerVocê não pode simplesmente dividir a string IP na ".", mapfunção string-to-número de Haskell sobre a seqüência de dividir e somar os resultados?
gato
2

Lua, 169 162 160 153 151 148 138 129 bytes

Versão Golfed

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

Requer que o Luasocket esteja instalado e um intérprete que suporte etiquetas. Eu testei com Luajit e também posso confirmar que o código não funciona com Lua 5.1.

Versão 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

Editar 1:

Alterado i=({c:getpeername()})[1]para apenasi=c:getpeername()

Edição 2:

Chaves removidas da instrução require.

Edição 3:

Removidas as chaves ao redor do vararg, diminuindo a contagem de bytes um pouco.

Edição 4:

Removidos os parênteses em torno de "% d +", menores em 2 bytes.

Edição 5:

Removida a variável desnecessária i.

Edição 6:

O ip foi alterado de "127.0.0.1" para 0. (Graças a xyzzy em #lua)

Edição 7:

Foi removida a chamada de função para tonumber, pois as strings são convertidas em números automaticamente (obrigado a Trebuchette pela sugestão, eu não sabia disso)

Seeseemelk
fonte
1
Apenas Lua 5.2 e até rótulos de apoio, se você está curioso
Trebuchette
1
Além disso, Lua converte automaticamente seqüências de caracteres em números com o +operador, para que você possa remover tonumber.
precisa
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)

Leva o número da porta como uma linha no stdin; requer network-simpleda Cabal.

Como sempre, com respostas de Haskell que não se restringem a funções puras, elas importsocupam muitos bytes. A nova linha à direita também vale 9 bytes ...

Um pouco semelhante à resposta de @ Jules, mas eu uso manipulação de strings em vez de operações de bytes. Eu também roubei a -XOverloadedStringsextensão, que provavelmente vale 19 bytes extra.

Actorclavilis
fonte
2

C, 243 188 bytes (ou talvez 217 162 bytes)

V2: veja abaixo as explicações.

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

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

Provavelmente mais golfe possível amanhã de manhã. Vou arrumar este post depois dessas atualizações.


V1:

Este foi realmente muito divertido de jogar golfe.

#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, é uma implementação direta. Os três componentes principais são

Criando o soquete:

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

Usamos as várias formas explícitas das constantes AF_INET etc, e fazemos uso do fato de que quando uma estrutura é inicializada em C dessa maneira, os elementos não especificados são definidos como zero.

Ouça os clientes, aceite-os e feche suas conexões:

for (escute (s, 8); c = aceite (s, & C, & g); q = fclose (g))

Finalmente, para enviar a cada cliente os dados:

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

O IP é armazenado em C.sin_addr.s_addr como um número inteiro de 32 bits, em que cada octeto é representado por um dos quatro bytes. Somamos esses bytes com o loop for e os imprimimos no fluxo usando fprintf.

Eu tenho uma solução de 217 bytes mais curta, mas não tenho certeza absoluta de que ela não viole as brechas padrão, pois exige que a porta seja fornecida unária na ordem de bytes da rede como argumentos de linha de comando. Ou seja, para executar o servidor na porta 12345, seria necessário chamar

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

onde o número total de 1s é 14640. Para dizer o mínimo, é um pouco ... complicado. Mas aqui está, de qualquer forma:

#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-
fonte
2

Raquete, 265 bytes

#lang racket(define l(tcp-listen(string->number(read-line))))(let e()(define-values(i o)(tcp-accept l))(thread(λ()(define-values(a b)(tcp-addresses o))(write(~a(foldl + 0(map string->number(string-split a".")))o))(newline o)(close-output-port o)))(e)))

Ungolfed:

#lang racket
(define listener (tcp-listen (string->number (read-line))))
(define (mk-server)
  (let echo-server ()
    (define-values (in out) (tcp-accept listener))
    (thread
     (λ()
       (define-values (a b) (tcp-addresses out))
       (write (number->string (foldl + 0(map string->number(string-split a "."))) out))
       (write "\n" out)
       (close-output-port out)))
    (echo-server)))
gato
fonte
2

Fator, 155 146 131 206 190 bytes

Bem, eu aprendi muito sobre programação de soquetes de baixo nível. Eu não acho que eu nunca quero fazer isso de novo, porque o meu thr cabeça dói.

[ 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 ]

Ah, sim, encadeado e não retorna, certo.

gato
fonte
Você pode usar em 10 base>vez de string>number?
fede s.
@fedes. Uau, eu nunca soube que isso existia. Acho que isso me permitirá encurtar muitas das minhas respostas do Fator!
cat
E 10 >basepara number> string, também.
fede s.
1
@fedes. Aqueles merecem uma resposta aqui : D
gato