Un simple serveur TCP

104

Ecrivez un programme ou une fonction qui écoute le trafic TCP entrant sur le port N. Il offre un service simple: il calcule la somme des champs d’adresse IP de la connexion entrante et le renvoie.

Le programme ou la fonction lit l'entier N à partir d'arguments ou de stdin. Il écoute les connexions TCP entrantes sur le port N. Lorsque quelqu'un se connecte à ce port, le programme calcule la somme de ses champs d'adresse IP et le renvoie au client avec un saut de ligne final et ferme la connexion.

  • Le numéro de port N est un port valide et 2 10 <N <2 15
  • Le retour à la ligne peut être \nou\r\n
  • Vous pouvez utiliser IPv4 ou IPv6. Les adresses IPv6 étant écrites au format hexadécimal, vous devez également fournir le résultat au même format, par exemple 2001:0db8:0000:0042:0000:8a2e:0370:7334 => 12ecd.

C'est du . Les règles standard et les échappatoires s'appliquent.

Exemple

Vous exécutez votre serveur avec ./server 1234. Le serveur est maintenant en cours d'exécution et attend des connexions sur le port 1234. Un client de se 127.0.0.1connecte ensuite à votre serveur. Votre serveur effectue un calcul simple: 127+0+0+1 => 128et envoie le résultat au client (avec saut de ligne): 128\n. Ensuite, le serveur ferme la connexion et attend le prochain client.

Classement

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
la source
1
Est-il permis d'utiliser inetd / xinetd ou similaire?
Traumatismes numériques
91
J'aime cela, car c’est un défi de golf que les langues de golf ne sont probablement pas très bonnes à jouer.
isaacg
9
Non seulement il est étonnant qu'un serveur TCP soit apparemment un programme très facile à écrire, mais je suis profondément déçu par le fait qu'il est joué au golf pour le plaisir. Je reviens à la lutte avec FizzBuzz comme un imbécile.
MonkeyZeus
17
@isaacg Il est temps que quelqu'un trouve le serveur TCP intégré à Mathematica
Version
3
@MonkeyZeus Pour être juste, vous ne verrez aucun bon serveur TCP ici. Création d' un serveur TCP fiable, évolutive qui gère toutes les subtilités de TCP (et votre protocole d'application) est bien un peu plus difficile: D Bien qu'il aide certainement que le protocole est extrêmement simple - vous ne même pas besoin de lire le flux, quelque chose que j'ai vu cassé dans trop de serveurs TCP pour compter: D
Luaan

Réponses:

57

Bash + netcat + ss +…, 65 60 caractères

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

Pas une solution sérieuse, était simplement curieux de cette possibilité.

Grâce à:

  • ninjalj pour avoir suggéré le awkfiltrage basé (-5 caractères)

Échantillon échantillon:

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

Sur Ubuntu , vous pouvez obtenir ncde netcat traditionnels (non, netcat-openbsd est pas bon) et ssde iproute2 .

homme au travail
la source
22
Pourquoi dites-vous que ce n'est pas une solution sérieuse? Tant que cela fonctionne comme prévu, je ne vois aucune raison pour que cela ne soit pas considéré comme sérieux. C'est aussi le plus court par une marge assez importante pour le moment.
Alex A.
La plus grande préoccupation à ce sujet est apparue au cours de la discussion avec @JesseSielaff lorsque j'ai appris que, sur les systèmes avec IPv6 configuré, les informations relatives aux sockets peuvent être formatées différemment. Ne pas avoir un tel système pour le tester. Pour ce que je pense s'il serait plus correct de le transformer en CW.
manatwork
3
D'après ce que je comprends de la spécification, vous devez prendre en charge IPv4 ou IPv6, pas les deux. Donc, tant que cela fonctionne pour IPv4, ne pas supporter IPv6 ne devrait pas avoir d'importance, je pense.
Alex A.
1
@Alexa. Au moins, je pense que ma question le dit. Dois-je clarifier cela?
Hannes Karppila
@HannesKarppila, votre question est claire. Le problème possible est que ma solution peut nécessiter que le système d'exploitation soit configuré d'une manière particulière pour pouvoir s'exécuter. Je suis donc inquiet car cela peut échouer si IPv6 est configuré, que je le gère ou non. Quelqu'un qui a IPv6 configuré pourrait le dire à coup sûr…
manatwork
23

C #, 284 283 282 278 274 254 octets

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

Exemple classique d'un serveur TCP C # basique. Essai:

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
la source
7
Vous pouvez enregistrer 1 octet en utilisant à la int Mainplace de void Main. Comme le programme ne retourne jamais, le compilateur n'a pas besoin d'une returndéclaration.
Raznagul
Et non, ça ne coule pas. En fait, il est assez déterministe de libérer des ressources également. En outre, l'argument Startest facultatif, ce qui permet de sauvegarder un autre caractère.
Luaan
@ Luan Ouais, cela a été laissé par le débogage.
LegionMammal978
En outre, vous pouvez utiliser usingsur le TcpClient, ce qui vous permettra d'économiser trois autres caractères (utilisez le {}de for), et faire de même avec le StreamWriterdevrait en sauver un de plus.
Luaan
@Luaan, je dois explicitement Flushle StreamWriterfaire fonctionner correctement.
LegionMammal978
22

Linux ELF / x86, 146 octets

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

Inclut un en-tête ELF de 52 octets, un en-tête de programme de 32 octets, 111 octets de code de programme + 3 octets de code permettant de sauter dans les en-têtes.

Information sur la façon de créer de petits executables ELF se trouve à breadbox d » « Un Whirlwind tutoriel sur la création vraiment Teensy ELF pour Linux Exécutables » .

Linux / i386 utilise l' socketcall(2)appel système multiplex, qui prend ebxl'appel de socket spécifique (les SYS_*macros de /usr/include/linux/net.h) et ecxun pointeur sur la zone d'argument de l'appel de bibliothèque d'origine.

Quelques choses faites pour garder le petit exécutable:

  • Cela suppose que les registres sont mis à zéro à l'entrée, ce que Linux fait, mais n'est pas requis par le standard ELF (la seule condition requise est que les EDXpoints d' entrée constituent une fonction de finalisation (utile pour les exécutables chargés par l'éditeur de liens dynamique) ou vaut NULL).
  • Il suppose au lancement (généralement par un shell) que les seuls descripteurs de fichier ouverts sont 0, 1 et 2. Ce qui signifie que le socket d’écoute sera fd 3 et le socket accepté sera fd 4.
  • Il suppose qu'il y a exactement 2 arguments (y compris argv[0]).
  • Le même espace de pile est réutilisé pour les appels à bind(2), listen(2)et accept(2).
  • Pour ignorer les champs phentsizeand phnum, un octet est ajouté, ce qui en fait une CMPopération qui prend immédiatement les champs phentsizeand phnum(astuce volée sans vergogne de la solution de breadbox à 123 dans anarchy golf ).
  • Les opérations sur les chaînes x86 LODS(chargement dans l’accumulateur et index source d’incrémentation / décrémentation) et STOS(stockage depuis l’index de destination de l’accumulateur et incrémentation / décrémentation) conviennent au code abrégé.
  • XCHG EAX, regest 1 octet, comparé à MOV EAX, reg, ce qui prend 2 octets.
  • CDQ/CLTD(sign-extend EAXinto EDX:EAX) peut être utilisé comme moyen sur 1 octet de mettre à zéro le EDXregistre.
  • BSWAPest utile pour la mise en œuvre htons().

Source 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
la source
4
Cette réponse est sous-estimée.
chat le
16

NodeJS, 146 134 127 octets

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

J'ai enfin la possibilité de poster une réponse à NodeJS! IPv4 seulement pour le moment.

Exécution échantillon: node script.js 1024. Depuis un autre terminal:

$ curl 127.0.0.1:1024
128
nickb
la source
2
Je compte actuellement 127 octets, même si vous pouvez le réduire à 126 en permutant '\n'avec une chaîne de modèle contenant un retour à la ligne littéral.
Mwr247
Est-ce que cela ne manquerait pas aux exigences parce que vous créez un serveur HTTP, je veux dire, techniquement, c'est un serveur TCP, mais vous ne pouvez pas simplement utiliser le module TCP et vous sauver un caractère?
MayorMonty
14

Tcl, 92

  • 1 octet enregistré grâce à @DonalFellows.
proc s {c a p} {puts $c [expr [string map .\ + $a]]
close $c}
socket -server s $argv
vwait f

Assez explicite:

socket -server s $argv crée un socket d’écoute sur le port spécifié dans les arguments.

Chaque fois qu’une nouvelle connexion arrive, l’ proc sappel est appelé, avec comme paramètres canal, adresse source et port source. string mapsubstitue .à +l'adresse de source, et exprévalue le résultat arithmétique, qui est ensuite putsde nouveau au canal de connexion c.

vwait exécute une boucle d'événements pour attraper les événements de connexion entrants.


Crédit à @DonalFellows pour les éléments suivants:

Voici une version qui gère IPv6 (nécessite Tcl 8.6; la plus grande partie de la longueur supplémentaire est due à la production d'une réponse hexadécimale):

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 numérique
la source
1
L'utilisation applyne semble rien sauver. Vous ne pouvez pas non plus l'utiliser tcl::mathop::+ {*}[split $a .]car c'est un peu plus long. Vous ne pouvez pas non plus raser quoi que ce soit parmi les noms d'options. Mais prendre en charge IPv6 est assez simple à ajouter et ne coûte que quelques octets de code de plus (et une regsubapproche basée sur la longueur est tout aussi longue).
Donal Fellows
ahhh, Tcl / Tcl-DP ... une multitude d'outils. (Dans les années 90, un professeur nous a montré que nous pouvions écrire un Excel distribué par le réseau (avec une grille et incluant l'évaluation des formules!) partagé entre plusieurs personnes possédant 4 lignes (courtes) pour le serveur et 5 pour les clients. ..
Olivier Dulac
proc s {c a p}avez-vous vraiment besoin de tout cet espace?
chat
12

Groovy 133 , 125 , 93 , 89

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

IPv4 seulement, probablement.

Ungolfed:

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

Essai:

$ telnet localhost 9000
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
128
Connection closed by foreign host.
Will Lp
la source
1
.toInteger()as intet s.inetAddress.address*.toInteger()(s.inetAddress.address as int[]). Et il y a un espace supplémentaire après .with.
Manatwork
@manatwork thx! Mis à jour.
Will Lp
9

Python 3, 170 166 147 octets

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

Prend le port stdin, IPv4 seulement. Fonctionne sous GNU / Linux (et, je suppose, dans la plupart des autres), qui s'étend automatiquement "" à "0.0.0.0", mais pas sûr de Windows.

sammko
la source
2
Vous pourriez économiser plusieurs octets. Premièrement, les espaces import *et , SOCK_STREAMsont inutiles. En outre, la ligne d'envoi pourrait être écrite plus efficacement en tant que c.send(b"%d\n"%eval(a[0].replace(".","+"))).
Hannes Karppila
2
@HannesKarppila oh, merci. oublié les espaces, le hack eval est assez cool cependant.
Sammko
2
AF_INET et SOCK_STREAM ne sont que des constantes; AF_INET est égal à 2 et SOCK_STREAM à 1. En outre, comme indiqué, SOCK_STREAM n'est pas nécessaire; afin que vous puissiez raccourcir cela en utilisant plutôt s=socket(2).
Skyler
1
ne pouvez-vous pas simplement faire socket () et donc sauvegarder un autre octet?
Foon
1
Vous pouvez sauvegarder 10 caractères en utilisant Python 2. Ensuite, int(input())devient input()et la partie envoi devientc.send(`eval(a[0].replace(".","+"))`)
Blender
9

Java, 371 368 350 344 333 310 295 282 octets

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

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

Sortie

mallard@steamroller:~$ telnet localhost 8888
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
128
Connection closed by foreign host.
Matthew Smith
la source
1
Retirez le int k=et remplacez le k par tous les éléments c Integer.toString(k). Pour économiser quelques octets.
GiantTree
1
Javas octet à peu près sûr gâche la valeur de retour pour 192.168.2.1 ou adresses similaires avec un octet ci-dessus 127.
AlexR
1
Changer interfacepour classdevrait gagner quelques octets de plus
ortis
2
Utilisez a.getOutputStream().write((c[0] + c[1] + c[2] + c[3]+"\n").getBytes());au lieu denew DataOutputStream(a.getOutputStream()).writeBytes(c[0] + c[1] + c[2] + c[3] + "\n")
ortis
3
N'est-ce pas try(Socket a=...){}plus court que a.close();? Nécessite Java 7, mais peut gagner des octets.
Olivier Grégoire
8

PowerShell v2 +, 303 268 257 227 octets

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

35 octets sauvés grâce à Matt ... 11 autres octets sauvés par aliasingNew-Object et modifications mineures ... 30 octets supplémentaires enregistrés en utilisant implicitement localhost plutôt que anyl'adresse IP et corrigés pour tenir compte de l'utilisation continue telle que spécifiée à l'origine et que j'ai manquée

Vraiment semblable à la réponse C # , puisque c'est .NET qui sous-tend les deux. Nous économisons quelques octets ici sur la réponse C # en étant en mesure de tirer parti de la fonctionnalité de renvoi de PowerShell (entourant notre déclaration / affectation en parenthèses, puis en appelant immédiatement les méthodes.), Mais nous perdons énormément en raison de la formulation de la somme. . Le fait que nous ayons des noms de classe / appels légèrement plus courts est vraiment la raison pour laquelle cette réponse bat C #.

Explication

Nous créons d’abord un New-Alias(avec l’ nalalias) pour économiser sur la recopie New-Objectplus tard. Le reste de la première ligne configure un écouteur TCP. Nous passons la ligne $args[0]de commande comme entrée pour créer un nouveau System.Net.Sockets.TcpListener, stocké sous $l. Cet objet est encapsulé dans des parenthèses et immédiatement appelé avec.Start() pour l’ouvrir activement.

En entrant dans une forboucle infinie , nous plaçons ensuite notre auditeur $lsur le blocage avec AcceptTcpClient()lequel attendre une connexion. Une référence à cette connexion (une fois établie) est stockée $c, encapsulée dans des parenthèses et immédiatement appelée GetStream()pour obtenir le flux de données. Ce flux de données est transmis à un nouveau System.IO.StreamWriterconstructeur $wafin que nous puissions le manipuler. Ce constructeur est lui-même encapsulé dans des parenthèses et immédiatement appelé Write(...).

Pendant l' Write(...)appel, nous prenons en charge notre client $cet obtenons la RemoteEndPointpropriété du client . C'est le seul moyen (que j'ai trouvé jusqu'à présent) d'obtenir l'adresse IP distante. Ensuite, nous devons reformuler cet [System.Net.IPEndPoint]objet en tant qu’objet afin qu’il soit correctement formaté, encapsuler cela entre parenthèses et extraire uniquement la .Addresspropriété. Nous avons ensuite -replaceles périodes littérales avec des signes plus, puis nous le transmettons à Invoke-Expression(similaire à eval) pour obtenir notre sommation.

Après l'écriture d'IO, nous devons appeler .Dispose()pour nous assurer que le flux de données est envoyé au client et fermé. Le serveur TCP interrompt la connexion client sans avertissement. Par conséquent, en fonction du client utilisé, il est possible que la communication soit interrompue pendant un certain temps. Il continue ensuite dans la forboucle sans fermer correctement les connexions. Cela signifie également que la mémoire et le système manquent de manière folle, mais nous ne nous en soucions pas, n'est-ce pas? Vous devrez peut-être utiliser le Gestionnaire des tâches pour arrêter le processus une fois que vous aurez fini d’exécuter le serveur. :RÉ

Également IPv4 uniquement, car la sommation indique une tentative spectaculaire de gestion d'une adresse IPv6, car ce :n'est pas un opérateur algébrique valide iexà analyser.

AdmBorkBork
la source
2
"Les fuites de mémoire et le système gère comme un fou" Quoi, avez-vous à free()eux après? delete[], peut être? : P
Chat
8
@tac Ouais, il y a toute une série de .close()et .dispose()méthodes que nous ne demandons pas ici qui inciterait les gens sur la révision du Code d'avoir un ajustement.
AdmBorkBork
Oh, n'est-ce pas PS GC'd? Ou le GC procède-t-il à un recomptage et non à une analyse de la portée?
Chat
@tac Oui, PowerShell dispose d'une récupération de place grâce au système .NET sous-jacent. Mais, selon la façon dont vous appelez ou exploitez ce script, vous pouvez rencontrer des bugs comme celui-ci qui perd de la mémoire dans le pipeline. Le code ci-dessus n'est pas non plus thread-safe et peut donc rencontrer des problèmes avec le GC, car nous ne fermons pas explicitement le socket.
AdmBorkBork
1
Lors des tests, je ne pouvais pas obtenir que cela fonctionne, probablement en raison de problèmes de pare-feu que je n'ai pas envie de corriger, donc je ne peux pas en être sûr, mais ... Je pense que vous pouvez supprimer "Système" de la plupart, sinon de tous les moulages vous avez là-à-dire: [Net.ipaddress]::Anytravaux.
Matt
7

PHP, 161 (56?)

Ceci est mon premier post ici. J'espère que ça va 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);}

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.

Cela ne fonctionne que pour IPV4

Edit : Je viens de remarquer que php supporte le serveur de base:
j'ai décidé de m'en tenir au nombre de caractères original à moins que quelqu'un ne confirme si le suivi est autorisé :)

test2.php: (solution possible sur 56 octets)

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

Et puis démarrez le service avec:

php -S localhost:8080 test2.php

Chrome en tant que client screenshot

Edit 2: wget en tant que client

$ wget -qO- localhost:8080
128
Mikael
la source
Je sais que les règles disent: "Le programme ou la fonction lit l'entier N à partir d'arguments ou de stdin", mais est-ce correct si programme dans ce cas est php lui-même? Ou l'utilisation du serveur intégré en php est-elle considérée comme une échappatoire?
Mikael
Bienvenue dans Programming Puzzles & Code Golf! Votre solution de 161 octets a fière allure. La solution à 56 octets que vous avez mentionnée est-elle la solution test2.php? Si tel est le cas, je pense que vous devriez demander au PO s'il jugerait ce type de fonctionnement intrinsèque acceptable pour ce défi. Ce n'est pas une faille cependant.
Alex A.
Je dirais que l'utilisation d'un serveur TCP intégré serait acceptable, mais dans ce cas, nous parlons d'un serveur HTTP intégré . Ainsi, la solution de 56 octets 1) ne fait rien si le client se connecte et n’envoie rien; 2) renvoie uniquement “[mer. 30 mars 10:15:02 2016] 127.0.0.1:47974 Requête non valide (requête HTTP mal formée)” sans exécuter test2.php dans le cas où le client envoie par exemple “foo”; 3) envoie l'ensemble complet des en-têtes de réponse HTTP avant la réponse requise réelle dans le cas où le client envoie une requête HTTP valide.
Manatwork
@Alex A. Merci et oui, la solution à 56 octets est à l'essai2.php :)
Mikael
@ manatwork Vous avez raison, mais je pensais que le client n'est pas clairement spécifié dans cette tâche. Donc, est-il possible d’utiliser un navigateur ou encore plus simple quelque chose comme "wget ​​-qO- localhost: 8080" en tant que client?
Mikael
7

Go , 359 311

C'est mon premier programme dans Go - Cela m'a permis de découvrir une chose: ce n'est vraiment pas une bonne langue pour jouer au golf!

(Bravo à @steve qui a fait la majeure partie du 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
la source
2
Mais c’est un bon langage pour faire un serveur TCP!
Numeri
1
Odd, le résultat est 360 quand je me connecte à partir de 192.168.0.67, plutôt que 427.
steve
3
Vous pouvez nommer les paquets strings + strconv pour économiser quelques octets. par exemple "strings"devient s "strings"pour que ce dernier strings.Splitdevienne juste s.Split.
steve
1
Quelques octets de moins ont été supprimés du site pastebin.com/HY84sazE - on commence à avoir l'air un peu plus «golfés» maintenant
steve Le
2
Si vous utilisez import(."pkgname")toutes les fonctions seront importées dans l'espace de noms actuel, vous pouvez alors supprimer le préfixe. par exemple. import ."fmt"; Println("foo") Si vous utilisez Sscanfle fmtpaquet pour analyser l'adresse au lieu de regex, cela vous épargnera quelques octets supplémentaires, ce qui vous donnera l'avantage de pouvoir Fprintlnrenvoyer le total au lieu d'importer strconv.
Kristoffer Sall-Storgaard
7

Common Lisp, 110 octets

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

Détails

(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
la source
2
Yay pour Lithp commun!
chat
6

q, 88 octets

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: Prend le deuxième argument de ligne de commande (le premier "-"sert à dire de qne pas interpréter en Ntant que script / fichier) et ouvre un port ( "p ") avec cet argument .
    • Remarque: L'appel q -p Ndéfinit Nautomatiquement le port , mais comme la question semble suggérer que cela Ndevrait être un argument pour le programme plutôt que l'exécutable lui-même, je suis allé dans le sens le plus long.
  • Dans la .z.pgfonction qui gère les demandes entrantes, .z.al'adresse IP est stockée sous forme d'entier 32 bits.
    • "i"$0x0 vsla scinde en son entier 'constituants' et sumfait la somme.
    • Enfin, stringle résultat numérique et ajouter "\n"à celui-ci pour retourner au client.
  • .z.ph est une autre fonction pour les requêtes HTTP GET, avec un traitement supplémentaire pour convertir la sortie de chaîne en une réponse HTTP valide.

Démo - Serveur:

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)

Démo - Client (d'une autre qsession en cours d'exécution 127.0.0.1):

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

Démo - Client (à partir de curl):

$ curl localhost:1234
128

$
hjk
la source
6

LiveScript, 107 105 octets

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

Rien d’autre à ajouter, c’est juste un truc de base sur NodeJS. Les points de style pour &1(second argument), <|(F # piping, semblable à $Haskell) et biop: (+)dans LS, sont comme des sections d'opérateur dans Haskell: une fonction binaire curryed (qui ajoute ses opérandes). Aussi un peu sale: /si une chaîne littérale se trouve à sa droite, elle se scinde.

Ven
la source
5

Perl, 141 132 + 1 = 133 octets

Golfé

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

Exemple

$ 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
la source
Êtes-vous sûr que c'est correct? Je reçois la somme imprimée sur le terminal du serveur, pas sur celui du client. Quoi qu'il en soit, vous pouvez supprimer toutes les parenthèses et modifier s/\./+/gy/./+/.
manatwork
Ahh, mal lu ... révisera en conséquence et incorporera votre bonne suggestion.
steve
1
while(1){…}{…;redo}selon user130144 grande l » extrémité . Et à l'exception de l' ->send()appel, toutes les autres parenthèses sont inutiles.
Manatwork
4

Python 2, 180 octets

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

Prend le port sur stdin.

Mixeur
la source
4

NodeJS (ES6), 129 118 107 octets

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

Fonctionne pour IPv4. Courir commenode server.js <port>

Mwr247
la source
En réalité, cela ne fonctionne pas si le serveur utilise IPv6 (comme par exemple le mien le fait automatiquement), car le c.remoteAddressserait alors ::ffff:127.0.0.1. (J'ai testé sur Node v5.9.1).
Frxstrem
De plus, vous n'avez pas de fin de ligne, ce qui devrait augmenter votre score de 2 octets.
Frxstrem
@Frxstrem Whoops, j'ai oublié cette nouvelle ligne. Ajoute seulement 1 octet si grâce aux chaînes de modèle. Concernant la famille IP: .listen()utilisé par défaut en premier sur IPv4, mais il semble que ce soit par bogue ou par conception que cela a changé. La soumission fonctionnera toujours correctement sur les versions les plus récentes du noeud lorsque IPv6 est désactivé sur la machine hôte.
Mwr247
4

Go, 211 octets

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

Peut probablement être joué au golf plus loin, je ne suis pas entièrement satisfait de la façon dont je dois analyser l'adresse IP, par exemple, cela ressemble à un horrible hack.

Ecoute sur IPv4 sur le port donné en argument.

Kristoffer Sall-Storgaard
la source
4

PowerShell, 208 206 192 152 octets

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

information sur la version:

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

Merci à TimmyD de m'avoir sauvé 14 octets!

Merci à TessellatingHeckler de m'avoir sauvé 40 octets

Nacht
la source
@TimmyD ah oups j'ai oublié que c'était nécessaire ... réparé
Nacht
L'une des manières dont les programmes sont autorisés à prendre des entrées est à partir de stdin. Je suppose que cette question particulière ne spécifie pas que cela est autorisé, mais que c'est un problème de code-golf général qui, à mon avis, devrait compter pour PowerShell. Malheureusement, cela diffère de bash en ce sens qu’il n’attend pas d’entrée sur stdin si aucune n’a été fournie.
Nacht
C'est suffisant. corrigé à nouveau
Nacht
Très bien, maintenant pour certains golfs - essayez ceci à l' ($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()}
adresse
1
Je pense que vous pouvez ramener cela à 152 - déposez new-object et convertissez directement, ignorez la conversion de tableau d'octets et effectuez une conversion de chaîne différemment, ne stockez pas $ x du tout et supprimez les paramètres restants dans send (), et devient ($t=[net.sockets.tcplistener]$args[0]).start();for(){($z=$t.acceptsocket()).send([char[]]"$($z.remoteendpoint.address-replace"\.","+"|iex)");$z.close()}- ce que j’ai seulement testé rapidement avec la connexion netcat, mais cela semble fonctionner de la même manière - la connexion à partir de localhost de toute façon.
TessellatingHeckler
4

Code machine 8086 (DOS 16 bits), 163 156 148 148 142 octets

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

Code de montage équivalent:

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

Cela suppose que ntcpdrvsoit chargé à INT 0x61(et à tout pilote de paquet approprié à 0x60). Compiler avec fasm tcpserv.asm.

Il a cependant quelques problèmes:

  • Il ne vérifie pas si l'argument est un numéro de port valide ou même un numéro.
  • Le client doit envoyer au moins un octet, car je n'arrive pas à trouver un autre moyen de savoir si un client s'est connecté.
  • Cela ne fonctionne qu'une fois et se bloque une seconde fois. Fonctionne à nouveau après un redémarrage.
  • La valeur renvoyée est complétée à gauche avec des zéros.
  • Ceci est ma toute première entrée de golf de code, et aussi mon tout premier programme 8086 asm. Je suis sûr qu'il y a moyen d'améliorer encore cela.
utilisateur5434231
la source
1
Vous pouvez simplement poster un vidage hexadécimal de la sortie compilée pour 148 octets
cat
Est-ce permis? Cela rendrait cette entrée un peu plus compétitive ...
user5434231
1
Bon, j'ai changé l'entrée en code machine. Également rasé quelques octets de plus en utilisant à la xor r,rplace de mov r,0.
user5434231
1
Je l'ai écrit sur une machine à dos où les nouvelles lignes sont CR LF, alors je suis allé avec cela. Quoi qu’il en soit, il est inutile de compter maintenant la taille de l’asm, autant le nettoyer un peu et ajouter quelques commentaires.
user5434231
1
Cela est censé se produire ici aussi, et cela fonctionne; int 0x61renvoie un port local aléatoire dans ax. Mais il change également l'adresse IP d'écoute en un certain nombre de déchets ( 4.2.0.0iirc)
user5434231
3

Haskell, 216 octets

Utilisation du package "network-simple" ( cabal install network-simple). Nécessite quelques extensions de langue ( -XOverloadedStrings -XNoMonomorphismRestriction) pour fonctionner.

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)

Il existe quelques simplifications possibles, notamment changer la wfonction pour renvoyer la somme directement plutôt qu'une liste, et utiliser une fonction plutôt qu'un programme afin que le numéro de port puisse être spécifié en tant qu'argument. Je n'imagine pas que cela réduirait beaucoup la taille, cependant. 20 octets peut-être?

Jules
la source
Agréable! Assez sûr que vous pouvez toujours raser quelques octets en renommant hors wde #, alors w h ndevient h#npour une économie de 2 octets par utilisation.
Actorclavilis
3

Oreillons, 114 à 115 octets

Golfé:

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

Il s'agit de la version InterSystems Caché de Mumps. S'il existe une version capable d'acquérir l'adresse TCP plus courte que celle utilisée ##class(%SYSTEM.TCPDevice).PeerAddr() (car elle représente presque un tiers du programme), elle aurait peut-être une meilleure chance contre certaines des autres langues déjà publiées. ... ;-)

Edit: Merci à @TimmyD - J'ai raté la lecture du port de STDIN ou des arguments au lieu d’être codée en dur. Édité; il a ajouté 1 octet au programme.

Zmerch
la source
@TimmyD - Ah, vous avez raison. Vous avez manqué cela en lisant les exigences. Éditera posthaste.
Zmerch
3

C, 535 octets

Eh bien, quelqu'un devait le faire.

J'ai ajouté un seul saut de ligne afin que le code publié compte en réalité 536 caractères.

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

compiler avec gcc [file_name] -o server

courir avec ./server [port]

se connecter avec telnet localhost [port]

Dunno
la source
3
Bonne réponse! Comme mentionné précédemment , vous pouvez économiser quelques octets en utilisant les valeurs réelles de certaines constantes, telles que AF_INET et SOCK_STREAM.
Hannes Karppila
2

Java, 210 octets

Golfé:

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

Étendu:

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

C’est l’ensemble des astuces que j’ai données dans d’autres réponses en Java, plus l’écriture en tant que fonction au lieu d’un programme complet, qui gagne environ 70 octets par rapport au programme.

Olivier Grégoire
la source
2

Haskell, 326 octets

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)

Malheureusement, j'ai dû utiliser Network.Socketpour obtenir l'accès à l'adresse IP distante sous forme d'entier plutôt que de chaîne. Cela aurait sauvé des dizaines de caractères si je pouvais le faire s <- listenOn (PortNumber n), plutôt que d'avoir à appeler explicitement socket, bindet listenindividuellement. Mais, malheureusement, Network.acceptme donne une chaîne d’ hôte , pas un entier d’ adresse IP , j’ai donc dû recourir àNetwork.Socket.accept ami et à des amis.

La fonction fprend un numéro de port en argument et crée un socket serveur ( s) sur ce port. Il appelle ensuite la fonction gavec la socket du serveur.gboucle pour toujours, acceptant les connexions. La fonction bprend une adresse IPv4 réelle et calcule la somme de ses chiffres.

Je suis sûr que quelqu'un, quelque part, peut le faire mieux que moi. Je voulais montrer à quel point les tâches de socket sont faciles en Haskell ... mais j'ai ensuite échoué lamentablement, car j'ai besoin d'un accès à l'adresse IP, qui n'est généralement pas facile à obtenir.

MathematicalOrchid
la source
Le paquetage "network-simple" fournit une interface beaucoup plus agréable qui transmet le SockAddr à une fonction que vous lui donnez, ce qui facilite les choses. Voir ma solution que je suis sur le point de poster ...
Jules
Quelques simplifications sont apparentes: (1) Je pense withSocketsDoque cela n’est nécessaire que sous Windows. Par conséquent, si vous utilisez Linux, vous pouvez l’ignorer. (2) 0xFF est un caractère plus long que 255; (3) convertir le socket en un descripteur et utiliser des E / S régulières est beaucoup plus long que l’utiliser Network.Socket.send. Oui, sendc'est obsolète, mais la raison n'est pas pertinente pour ce scénario (elle ne concerne que du texte non binaire ASCII ou des données binaires), il semble donc raisonnable de l'utiliser.
Jules
Network.accept gives me a host string, not an IP address integerVous ne pouvez pas diviser simplement la chaîne IP sur la ".", mapfonction chaîne à nombre de Haskell sur la chaîne de division et résumer les résultats?
chat
2

Lua, 169 162 160 153 151 148 138 129 octets

Version golfée

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

Luasocket doit être installé et un interpréteur prenant en charge les étiquettes. Je l'ai testé avec Luajit et je peux également confirmer que le code ne fonctionne pas avec Lua 5.1.

Version non-golfée

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

Modifier 1:

Changé i=({c:getpeername()})[1]pour justei=c:getpeername()

Edit 2:

Suppression des accolades de l'instruction require.

Edit 3:

Suppression des accolades autour du vararg, diminution du nombre d'octets un peu.

Edit 4:

Suppression de la parenthèse autour de "% d +", raccourcie de 2 octets.

Edit 5:

Suppression de la variable inutile i.

Edit 6:

Changement de l'ip de "127.0.0.1" à 0. (Merci à xyzzy sur #lua)

Éditer 7:

Suppression de l'appel de fonction au numéro de numérotation puisque les chaînes sont automatiquement numérotées (Merci à Trebuchette pour cette suggestion, je ne le savais pas)

Seeseemelk
la source
1
Seuls Lua 5.2 et des étiquettes de soutien, si vous êtes curieux
Trebuchette
1
En outre, Lua transforme automatiquement les chaînes en chiffres avec l' +opérateur, afin que vous puissiez en sortir tonumber.
Trébuchette
2

Haskell, 185 (+ 19 = 204)? octets

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)

Prend le numéro de port comme une ligne sur stdin; nécessite network-simplede Cabal.

Comme d'habitude avec les réponses Haskell qui ne se limitent pas à des fonctions pures, elles importsprennent beaucoup trop d'octets. Le retour à la ligne qui précède vaut également 9 octets ...

Un peu similaire à la réponse de @ Jules, mais j'utilise la manipulation de chaîne au lieu d'opérations sur les octets. J'ai volé utilisé le -XOverloadedStringsprolongement et, ce qui est probablement une valeur de 19 octets supplémentaires.

Acteurclavilis
la source
2

C, 243 188 octets (ou peut-être 217 162 octets)

V2: voir ci-dessous pour les explications.

188 octets:

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

Légèrement circonscrit 162 octets:

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

Probablement plus de golf possible demain matin. Je vais ranger ce post après ces mises à jour.


V1:

Celui-ci était vraiment amusant au 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);}}

Cela fonctionne pour IPv4. La plupart du temps, c'est une implémentation simple. Les trois composantes principales sont

Création du socket:

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

Nous utilisons les différentes formes explicites des constantes AF_INET, etc., et utilisons le fait que lorsqu'une structure est initialisée en C, les éléments non spécifiés sont mis à zéro.

Écoutez les clients, acceptez-les et fermez leurs relations:

pour (écouter (s, 8); c = accepter (s, & C, & g); q = fclose (g))

Enfin pour envoyer les données à chaque client:

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

L'IP est stocké dans C.sin_addr.s_addrun entier de 32 bits, chaque octet étant représenté par l'un des quatre octets. Nous additionnons ces octets avec la boucle for puis les imprimons dans le flux à l’aide de fprintf.

J'ai une solution plus courte de 217 octets mais je ne suis pas tout à fait sûr qu'elle ne viole pas les failles standard, car elle nécessite que le port soit donné de manière unaire dans l'ordre des octets du réseau en tant qu'arguments de ligne de commande. Autrement dit, pour exécuter le serveur sur le port 12345, il faut appeler

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

où le nombre total de 1s est 14640. Pour le moins, c'est un peu ... encombrant. Mais la voici quand même:

#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-
la source
2

Raquette, 265 octets

#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)))
chat
la source
2

Facteur, 155 146 131 206 190 octets

Eh bien, je viens d’apprendre beaucoup de choses sur la programmation de sockets de bas niveau. Je ne pense pas que je veux jamais faire ça à nouveau, parce que mon Thr mal à la tête.

[ 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 oui, enfilé, et ne revient pas, d'accord.

chat
la source
Pouvez-vous utiliser 10 base>au lieu de string>number?
fede s.
@fedes. Wow, je n'ai jamais su que cela existait. Je pense que cela me permettra de raccourcir beaucoup de mes réponses de Factor!
chat du
Et 10 >basepour number> string, aussi.
fede s.
1
@fedes. Ceux qui méritent une réponse ici : D
cat