Ein einfacher TCP-Server


104

Schreiben Sie ein Programm oder eine Funktion, die auf eingehenden TCP-Verkehr an Port N wartet. Es bietet einen einfachen Dienst: Es berechnet die Summe der IP-Adressfelder der eingehenden Verbindung und kehrt zurück.

Programm oder Funktion liest Integer N aus Argumenten oder stdin. Es lauscht eingehenden TCP-Verbindungen an Port N. Wenn jemand eine Verbindung zu diesem Port herstellt, berechnet das Programm die Summe seiner IP-Adressfelder und sendet sie mit nachfolgendem Zeilenumbruch an den Client zurück und schließt die Verbindung.

  • Portnummer N ist ein gültiger Port und 2 10 <N <2 15
  • Der abschließende Zeilenumbruch kann entweder \noder sein\r\n
  • Sie können entweder IPv4 oder IPv6 verwenden. Da IPv6-Adressen hexadezimal geschrieben sind, müssen Sie beispielsweise auch das Ergebnis in demselben Format angeben 2001:0db8:0000:0042:0000:8a2e:0370:7334 => 12ecd.

Das ist . Es gelten Standardregeln und Regelungslücken.

Beispiel

Sie betreiben Ihren Server mit ./server 1234. Der Server wird jetzt ausgeführt und wartet auf Verbindungen an Port 1234. Dann stellt ein Client von eine 127.0.0.1Verbindung zu Ihrem Server her. Der Server führt eine einfache Rechnung: 127+0+0+1 => 128und sendet das Ergebnis an den Client (mit Newline nachgestellt): 128\n. Dann schließt der Server die Verbindung und wartet auf den nächsten Client.

Bestenliste

var QUESTION_ID=76379,OVERRIDE_USER=20569;function answersUrl(e){return"https://api.stackexchange.com/2.2/questions/"+QUESTION_ID+"/answers?page="+e+"&pagesize=100&order=desc&sort=creation&site=codegolf&filter="+ANSWER_FILTER}function commentUrl(e,s){return"https://api.stackexchange.com/2.2/answers/"+s.join(";")+"/comments?page="+e+"&pagesize=100&order=desc&sort=creation&site=codegolf&filter="+COMMENT_FILTER}function getAnswers(){jQuery.ajax({url:answersUrl(answer_page++),method:"get",dataType:"jsonp",crossDomain:!0,success:function(e){answers.push.apply(answers,e.items),answers_hash=[],answer_ids=[],e.items.forEach(function(e){e.comments=[];var s=+e.share_link.match(/\d+/);answer_ids.push(s),answers_hash[s]=e}),e.has_more||(more_answers=!1),comment_page=1,getComments()}})}function getComments(){jQuery.ajax({url:commentUrl(comment_page++,answer_ids),method:"get",dataType:"jsonp",crossDomain:!0,success:function(e){e.items.forEach(function(e){e.owner.user_id===OVERRIDE_USER&&answers_hash[e.post_id].comments.push(e)}),e.has_more?getComments():more_answers?getAnswers():process()}})}function getAuthorName(e){return e.owner.display_name}function process(){var e=[];answers.forEach(function(s){var r=s.body;s.comments.forEach(function(e){OVERRIDE_REG.test(e.body)&&(r="<h1>"+e.body.replace(OVERRIDE_REG,"")+"</h1>")});var a=r.match(SCORE_REG);a&&e.push({user:getAuthorName(s),size:+a[2],language:a[1],link:s.share_link})}),e.sort(function(e,s){var r=e.size,a=s.size;return r-a});var s={},r=1,a=null,n=1;e.forEach(function(e){e.size!=a&&(n=r),a=e.size,++r;var t=jQuery("#answer-template").html();t=t.replace("{{PLACE}}",n+".").replace("{{NAME}}",e.user).replace("{{LANGUAGE}}",e.language).replace("{{SIZE}}",e.size).replace("{{LINK}}",e.link),t=jQuery(t),jQuery("#answers").append(t);var o=e.language;/<a/.test(o)&&(o=jQuery(o).text()),s[o]=s[o]||{lang:e.language,user:e.user,size:e.size,link:e.link}});var t=[];for(var o in s)s.hasOwnProperty(o)&&t.push(s[o]);t.sort(function(e,s){return e.lang>s.lang?1:e.lang<s.lang?-1:0});for(var c=0;c<t.length;++c){var i=jQuery("#language-template").html(),o=t[c];i=i.replace("{{LANGUAGE}}",o.lang).replace("{{NAME}}",o.user).replace("{{SIZE}}",o.size).replace("{{LINK}}",o.link),i=jQuery(i),jQuery("#languages").append(i)}}var ANSWER_FILTER="!t)IWYnsLAZle2tQ3KqrVveCRJfxcRLe",COMMENT_FILTER="!)Q2B_A2kjfAiU78X(md6BoYk",answers=[],answers_hash,answer_ids,answer_page=1,more_answers=!0,comment_page;getAnswers();var SCORE_REG=/<h\d>\s*([^\n,]*[^\s,]),.*?(\d+)(?=[^\n\d<>]*(?:<(?:s>[^\n<>]*<\/s>|[^\n<>]+>)[^\n\d<>]*)*<\/h\d>)/,OVERRIDE_REG=/^Override\s*header:\s*/i;
body{text-align:left!important}#answer-list,#language-list{padding:10px;width:290px;float:left}table thead{font-weight:700}table td{padding:5px}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <link rel="stylesheet" type="text/css" href="//cdn.sstatic.net/codegolf/all.css?v=83c949450c8b"> <div id="answer-list"> <h2>Leaderboard</h2> <table class="answer-list"> <thead> <tr><td></td><td>Author</td><td>Language</td><td>Size</td></tr></thead> <tbody id="answers"> </tbody> </table> </div><div id="language-list"> <h2>Winners by Language</h2> <table class="language-list"> <thead> <tr><td>Language</td><td>User</td><td>Score</td></tr></thead> <tbody id="languages"> </tbody> </table> </div><table style="display: none"> <tbody id="answer-template"> <tr><td>{{PLACE}}</td><td>{{NAME}}</td><td>{{LANGUAGE}}</td><td>{{SIZE}}</td><td><a href="{{LINK}}">Link</a></td></tr></tbody> </table> <table style="display: none"> <tbody id="language-template"> <tr><td>{{LANGUAGE}}</td><td>{{NAME}}</td><td>{{SIZE}}</td><td><a href="{{LINK}}">Link</a></td></tr></tbody> </table>


1
Darf man inetd / xinetd oder ähnliches benutzen?
Digital Trauma

91
Ich mag das, da es eine Golfherausforderung ist, in der Golfsprachen wahrscheinlich nicht sehr gut sind.
Isaacg

9
Es ist nicht nur erstaunlich, dass ein TCP-Server anscheinend ein sehr einfach zu schreibendes Programm ist, ich bin gründlich über die Tatsache hinwegtäuscht, dass er zum Spaß golfen wird. Ich werde einfach wieder mit FizzBuzz wie einem Idioten kämpfen.
MonkeyZeus

17
@isaacg Es ist nur Zeit, bis jemand den in Mathematica
integrierten

3
@MonkeyZeus Um fair zu sein, werden Sie hier keinen guten TCP-Server sehen. Es ist etwas schwieriger, einen zuverlässigen, skalierbaren TCP-Server zu erstellen, der alle Feinheiten von TCP (und Ihrem Anwendungsprotokoll) gut handhabt: D Das Protokoll ist zwar sehr einfach, aber Sie müssen nicht einmal den Stream lesen Ich habe gesehen, dass zu viele TCP-Server kaputt sind, um sie zu zählen: D
Luaan

Antworten:


57

Bash + netcat + ss +…, 65 60 Zeichen

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

Keine ernsthafte Lösung, war nur neugierig auf diese Möglichkeit.

Dank an:

  • Ninjalj für das Vorschlagen der awkbasierten Filterung (-5 Zeichen)

Probelauf:

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

Auf Ubuntu kann man ncvon Netcat-Traditional (nein, Netcat-OpenBSD ist nicht gut) und ssvon iproute2 bekommen .


22
Warum ist das keine ernsthafte Lösung? Solange es wie erwartet funktioniert, sehe ich keinen Grund, warum es nicht als ernst anzusehen ist. Es ist im Moment auch das mit Abstand kürzeste.
Alex A.

Die größte Sorge dagegen zeigte sich während der Diskussion mit @JesseSielaff, als ich erfuhr, dass auf Systemen mit konfiguriertem IPv6 die Socket-bezogenen Informationen möglicherweise anders formatiert sind. Habe kein solches System, um es zu testen. Für die ich denke, ob es richtiger wäre, es in CW zu verwandeln.
Manatwork

3
Mein Verständnis der Spezifikation ist, dass Sie IPv4 oder IPv6 unterstützen müssen, nicht beides. So lange es für IPv4 funktioniert, sollte es keine Rolle spielen, IPv6 nicht zu unterstützen, denke ich.
Alex A.

1
@AlexA. Zumindest denke ich, dass meine Frage dies sagt. Soll ich das klären?
Hannes Karppila

@HannesKarppila, deine Frage ist klar. Das mögliche Problem ist, dass meine Lösung möglicherweise erfordert, dass das Betriebssystem auf eine bestimmte Weise konfiguriert ist, damit es ausgeführt werden kann. Ich mache mir also Sorgen, weil es fehlschlagen kann, wenn IPv6 konfiguriert ist, unabhängig davon, ob ich damit umgehe oder nicht. Jemand, der IPv6 konfiguriert hat, könnte es sicher sagen ...
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]);}}}

Klassisches Beispiel eines einfachen C # TCP-Servers. Testen:

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

Feuerfuchs:


7
Sie können 1 Byte sparen, indem Sie int Mainanstelle von verwenden void Main. Da das Programm niemals zurückgibt, benötigt der Compiler keine returnAnweisung.
Raznagul

Und nein, es leckt nicht. Es ist eigentlich ziemlich deterministisch, auch Ressourcen freizugeben. Das Argument für Startist optional und speichert ein anderes Zeichen.
Luaan

@Luaan Ja, das war vom Debuggen übrig.
LegionMammal978

Auch könnten Sie usingauf das TcpClient, was Sie drei weitere Zeichen sparen (verwenden Sie die {}von den for), und tut das gleiche mit dem StreamWritersollte man mehr sparen.
Luaan

@Luaan Ich muss ausdrücklich Flushdie StreamWriterdamit es richtig funktioniert.
LegionMammal978

22

Linux ELF / x86, 146 Bytes

00000000  7f 45 4c 46 01 00 00 00  5a 0e 00 00 5a 5e eb 10  |.ELF....Z...Z^..|
00000010  02 00 03 00 0c 50 eb 10  0c 50 eb 10 04 00 00 00  |.....P...P......|
00000020  5e 53 43 53 52 89 e1 b0  66 3d 20 00 01 00 cd 80  |^SCSR...f= .....|
00000030  97 55 6b ed 0a 01 c5 ac  2c 30 79 f6 43 0f cd 01  |.Uk.....,0y.C...|
00000040  dd 55 89 e1 6a 10 51 6a  10 51 57 89 e1 b0 66 cd  |.U..j.Qj.QW...f.|
00000050  80 43 43 b0 66 cd 80 01  64 24 08 89 e1 43 b0 66  |.CC.f...d$...C.f|
00000060  cd 80 89 c1 93 8d 74 24  1b 99 fd ac 01 c2 e2 fb  |......t$........|
00000070  89 f7 b0 0a aa 91 92 f6  f1 86 c4 04 30 aa 42 c1  |............0.B.|
00000080  e8 08 75 f3 42 89 f9 41  b0 04 cd 80 b0 06 cd 80  |..u.B..A........|
00000090  eb c9                                             |..|
00000092

Beinhaltet einen 52-Byte-ELF-Header, einen 32-Byte-Programmheader, 111 Byte Programmcode + 3 Byte Code zum Überspringen in den Headern.

Informationen darüber , wie kleines ELF - Executables erstellen finden Sie unter breadbox ‚s Ein Whirlwind Tutorial zum Erstellen von Really Teensy ELF ausführbaren Dateien für Linux .

Linux / i386 verwendet den socketcall(2)Multiplex-Systemaufruf, der ebxden spezifischen Socket-Aufruf (die SYS_*Makros von /usr/include/linux/net.h) und ecxeinen Zeiger auf den Argumentbereich des ursprünglichen Bibliotheksaufrufs aufnimmt.

Einige Maßnahmen, um die ausführbare Datei klein zu halten:

  • Es wird davon ausgegangen, dass die Register bei der Eingabe auf Null gesetzt werden, wie dies Linux tut, dies wird jedoch vom ELF-Standard nicht verlangt (die einzige Voraussetzung ist, dass bei der Eingabe EDXauf eine Finalisierungsfunktion verwiesen wird (nützlich für ausführbare Dateien, die vom dynamischen Linker geladen werden) oder NULL ist).
  • Es wird davon ausgegangen, dass beim Start (normalerweise von einer Shell) die einzigen offenen Dateideskriptoren 0, 1 und 2 sind. Dies bedeutet, dass der Listening-Socket fd 3 und der akzeptierte Socket fd 4 ist.
  • Es wird davon ausgegangen, dass es genau 2 Argumente gibt (einschließlich argv[0]).
  • Der gleiche Stapelspeicher wird für die Anrufe wieder verwendet bind(2), listen(2)und accept(2).
  • Um die zu überspringen phentsizeund phnumFelder, ein Byte vorangestellt wird, in eine CMPDrehoperation , die die Takes phentsizeund phnumFelder als unmittelbares (Trick aus schamlos gestohlen breadbox-Lösung auf 123 in Anarchie Golf ).
  • x86-Zeichenfolgenoperationen LODS(Laden in den Akkumulator und Inkrementieren / Dekrementieren des Quellindex) und STOS(Speichern aus dem Akkumulator und Inkrementieren / Dekrementieren des Zielindex) eignen sich gut für Funktionscode.
  • XCHG EAX, regist 1 Byte im Vergleich zu MOV EAX, reg2 Byte.
  • CDQ/CLTD(Vorzeichenerweiterung EAXin EDX:EAX) kann als 1-Byte-Methode zum Nullsetzen des EDXRegisters verwendet werden.
  • BSWAPist nützlich für die Implementierung htons().

Nasm-Quelle:

BITS 32                                         ;
                                                ;   ELF HEADER    --   PROGRAM HEADER
; ELF HEADER                                    ; +-------------+
DB 0x7f,'E','L','F'                             ; | magic       |    +--------------------+
                                                ; |             |    |                    |
; PROGRAM HEADERS                               ; |             |    |                    |
DD 1                                            ; |*class   32b | -- | type: PT_LOAD      |
                                                ; |*data   none |    |                    |
                                                ; |*version   0 |    |                    |
                                                ; |*ABI    SysV |    |                    |
DD 0xe5a        ; offset = vaddr & (PAGE_SIZE-1); |*ABI vers    | -- | offset             |
                                                ; |             |    |                    |
entry:  pop     edx     ; edx = 2 (argc)        ; |*PADx7       | -- | vaddr = 0x10eb5e5a |
        pop     esi     ; discard argv[0]       ; |             |    |                    |
        jmp     short skip                      ; |             |    |                    |
DW 2                                            ; | ET_EXEC     | -- |*paddr LO           |
DW 3                                            ; | EM_386      | -- |*paddr HI           |
DD 0x10eb500c                                   ; |*version     | -- | filesz             |
DD 0x10eb500c                                   ; | entry point | -- | memsz              |
DD 4                                            ; | ph offset   | -- | flags: RX          |
                                                ; |             |    |                    |
skip:   pop     esi     ; esi = argv[1]         ; |*sh offset   | -- |*align              |
socket: push    ebx     ; default protocol (0)  ; |             |    |                    |
        inc     ebx                             ; |             |    |                    |
        push    ebx     ; SOCK_STREAM (1)       ; |             |    |                    |
        push    edx     ; AF_INET (2)           ; |*flags       |    +--------------------+
        mov     ecx, esp                        ; |             |
        mov     al, 0x66                        ; |*ehsize      |
DB 0x3d         ; cmp eax,0x10020               ; |             |
DW 32                                           ; | phentsize   |
DW 1                                            ; | phnum       |
                                                ; |             |
        int     0x80    ; socket(2, 1, 0)       ; |*shentsize   |
        xchg    edi, eax; edi = sockfd, eax = 0 ; |*shnum       |
        push    ebp     ; INADDR_ANY            ; |             |
                                                ; |             |
mult:   imul    ebp, 10 ; \_                    ; |*shstrndx    |
        add     ebp, eax; >                     ; |             |
        lodsb           ; >                     ; +-------------+
        sub     al,'0'  ; >
        jns     mult    ; / ebp = atoi(argv[1])                 ;       bind stack frame
                                                                ;    +-----------------------+
endmul: inc     ebx             ; SYS_BIND (2)                  ;    |        INADDR_ANY     |
                                                                ; +->| AF_INET | htons(port) |
        bswap   ebp                                             ; |  +-----------------------+
        add     ebp, ebx        ; AF_INET (2), htons(port)      ; |  |           16          |
        push    ebp                                             ; |  +-----------------------+
                                                                ; |  |         dummy         |
        mov     ecx, esp                                        ; |  +-----------------------+
        push    16              ; addrlen                       ; |  |           16          |
        push    ecx             ; dummy value                   ; |  +-----------------------+
        push    16              ; addrlen                       ; +--|          addr         |
        push    ecx             ; addr                          ;    +-----------------------+
        push    edi             ; sock                          ;    |         sockfd        |
        mov     ecx, esp                                        ;    +-----------------------+
        mov     al, 0x66
        int     0x80            ; bind(sockfd, addr, addrlen)
                                                                ;       accept stack frame
                                                                ;    +-----------------------+
listen: ;mov    byte [esp+8],1                                  ;    |        INADDR_ANY     |
        inc     ebx                                             ; +->| AF_INET | htons(port) |
        inc     ebx             ; SYS_LISTEN (4)                ; |  +-----------------------+
        mov     al, 0x66                                        ; |+>|           16          |
        int     0x80            ; listen(sockfd, backlog)       ; || +-----------------------+
                                                                ; || |         dummy         |
        add     [esp+8], esp                                    ; || +-----------------------+
accept: mov     ecx, esp                                        ; |+-|        &addrlen       |
        inc     ebx             ; SYS_ACCEPT (5)                ; |  +-----------------------+
        mov     al, 0x66                                        ; +--|          addr         |
        int     0x80            ; accept(sockfd, addr, &addrlen);    +-----------------------+
                                                                ;    |         sockfd        |
        mov     ecx, eax        ; ecx = 4                       ;    +-----------------------+
        xchg    ebx, eax        ; ebx = acceptfd, eax = 000000xx

        lea     esi, [esp+27]   ; point to the IP part of struct sockaddr_in
        cdq

        std                     ; reverse direction for string operations
addip:  lodsb                   ; \_
        add     edx, eax        ; > edx = sum of 4 IP bytes
        loop    addip           ; /

        mov     edi, esi        ; reuse struct sockaddr_in as scratch buffer
        mov     al, 10          ; '\n'
        stosb
        xchg    ecx, eax        ; ecx = 10
        xchg    eax, edx        ; edx = 0, eax = sum

divide: div     cl              ; \_
        xchg    al, ah          ; >
        add     al,0x30         ; >
        stosb                   ; > sprintf(scratch, "%d", sum)
        inc     edx             ; >
        shr     eax, 8          ; >
        jnz     divide          ; /

write:  inc     edx             ; ndigits + 1 ('\n')
        mov     ecx, edi
        inc     ecx
        mov     al,4
        int     0x80            ; write(acceptfd, scratch, scratchlen) 
close:  mov     al, 6
        int     0x80            ; close(acceptfd)
        jmp     accept

4
Diese Antwort wird viel zu wenig gewürdigt.
Katze

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

Ich kann endlich eine NodeJS-Antwort schreiben! IPv4 nur jetzt.

Beispielausführung: node script.js 1024. Von einem anderen Terminal:

$ curl 127.0.0.1:1024
128

2
Ich zähle gerade 127 Bytes, obwohl Sie es auf 126 '\n'reduzieren können, indem Sie es mit einem Template-String austauschen, der eine wörtliche Newline enthält.
Mwr247

Würde dies nicht den Anforderungen genügen, da Sie einen HTTP-Server erstellen, ich meine, es ist technisch gesehen ein TCP-Server, aber könnten Sie nicht einfach das TCP-Modul verwenden und sich einen Charakter sichern?
MayorMonty

14

Tcl, 92

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

Ziemlich selbsterklärend:

socket -server s $argv Erstellt einen Listening-Socket an dem in den Argumenten angegebenen Port.

Bei jedem neuen Verbindungsaufbau wird der proc smit Kanal, Quelladresse und Quellport als Parameter aufgerufen. string mapersetzt .für +die Quelladresse und exprwertet arithmetisch das Ergebnis, das dann putszurück zu dem Verbindungskanal c.

vwait führt eine Ereignisschleife aus, um die eingehenden Verbindungsereignisse abzufangen.


Gutschrift an @DonalFellows für Folgendes:

Hier ist eine Version, die IPv6 unterstützt (erfordert Tcl 8.6; der größte Teil der zusätzlichen Länge ergibt sich aus der Erzeugung einer Hex-Antwort):

Tcl, 109

proc s {c a p} {puts $c [format %x [expr 0x[string map :\ +0x0 $a]]]
close $c}
socket -server s $argv
vwait f

1
Mit applyscheint nichts zu retten. Sie können es auch nicht verwenden, tcl::mathop::+ {*}[split $a .]da es etwas länger ist. Sie können auch nichts von Optionsnamen rasieren. Die Unterstützung von IPv6 ist jedoch ziemlich regsubeinfach hinzuzufügen und kostet nur ein paar Bytes mehr Code (und dann ist ein auf IPv6 basierender Ansatz genauso lang).
Donal Fellows

ahhh, Tcl / Tcl-DP ... unglaublich viele Tools. (In den 90er Jahren zeigte uns ein Professor, dass wir ein netzwerkverteiltes Excel (mit einem Raster und einer Formelauswertung!) schreiben konnten, das von mehreren Personen mit (iirc) 4 (kurzen) Zeilen für den Server und 5 für die Clients geteilt wurde. ..
Olivier Dulac

proc s {c a p}Brauchen Sie wirklich all das Leerzeichen?
Katze

12

Groovy 133 , 125 , 93 , 89

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

Wahrscheinlich nur IPv4.

Ungolfed:

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

Testen:

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

1
.toInteger()as intund s.inetAddress.address*.toInteger()(s.inetAddress.address as int[]). Und es gibt einen zusätzlichen Raum danach .with.
Manatwork

@manatwork Danke! Aktualisiert.
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()

Nimmt Port an stdin, nur IPv4. Funktioniert unter GNU / Linux (und, wie ich annehme, den meisten anderen Unices), das sich "" automatisch zu "0.0.0.0" erweitert, wobei Windows nicht sicher ist.


2
Sie könnten mehrere Bytes sparen. Erstens sind Leerzeichen in import *und , SOCK_STREAMunnötig. Auch die Sendeleitung könnte so effizienter geschrieben werden c.send(b"%d\n"%eval(a[0].replace(".","+"))).
Hannes Karppila

2
@ HannesKarppila oh, danke. Ich habe die Räume vergessen, aber der Eval-Hack ist ziemlich cool.
Sammko

2
AF_INET und SOCK_STREAM sind nur Konstanten. AF_INET ist 2 und SOCK_STREAM ist 1. Wie bereits erwähnt, ist SOCK_STREAM nicht erforderlich. Sie können dies also abkürzen, indem Sie stattdessen verwenden s=socket(2).
Skyler

1
kannst du nicht einfach socket () machen und somit ein weiteres Byte speichern?
Foon

1
Sie können 10 Zeichen mit Python 2 speichern. Dann int(input())wird input()und der Sendeteil wirdc.send(`eval(a[0].replace(".","+"))`)
Blender

9

Java, 371 368 350 344 333 310 295 282 Bytes

Golf gespielt

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

Ausgabe

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

1
Entfernen Sie die int k=und ersetzen Sie die k mit allen Dingen in Integer.toString(k). Um ein paar Bytes zu sparen.
GiantTree

1
Javas Byte ziemlich sicher vermasselt den Rückgabewert für 192.168.2.1 oder ähnliche Adressen mit einem Byte über 127.
AlexR

1
Wechsel interfacezu classmüssen gewinnen paar Byte
ortis

2
Verwenden Sie a.getOutputStream().write((c[0] + c[1] + c[2] + c[3]+"\n").getBytes());anstelle vonnew DataOutputStream(a.getOutputStream()).writeBytes(c[0] + c[1] + c[2] + c[3] + "\n")
ortis

3
Ist nicht try(Socket a=...){}kürzer als a.close();? Benötigt Java 7, kann aber Bytes gewinnen.
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()}

35 Bytes dank Matt gespeichert ... Weitere 11 Bytes durch Aliasing New-Objectund kleinere Änderungen gespeichert ... Weitere 30 Bytes durch implizite Verwendung von localhost anstelle der anyIP-Adresse gespeichert und korrigiert, um die ursprünglich angegebene fortgesetzte Verwendung zu berücksichtigen, und ich habe sie verpasst

Wirklich ähnlich wie die C # -Antwort , da es sich um .NET handelt, das beiden zugrunde liegt. Wir sparen hier ein paar Bytes gegenüber der C # -Antwort, indem wir die Rückgabefunktionalität von PowerShell (um unsere Deklaration / Zuweisung in Parens und den sofortigen Aufruf der. -Methoden) nutzen können . Die Tatsache, dass wir etwas kürzere Klassennamen / -aufrufe haben, ist wirklich der Grund, warum diese Antwort C # schlägt.

Erläuterung

Wir erstellen zuerst ein New-Alias(mit dem nalAlias), um zu einem New-Objectspäteren Zeitpunkt die erneute Eingabe zu speichern . Der Rest der ersten Zeile richtet einen TCP-Listener ein. Wir übergeben die Befehlszeile $args[0]als Eingabe für die Erstellung eines neuen System.Net.Sockets.TcpListener, gespeicherten As $l. Dieses Objekt wird in Parens eingekapselt und sofort mit aufgerufen .Start(), damit es den Socket aktiv öffnet.

forWir treten in eine Endlosschleife ein und setzen unseren Listener $lauf Blocking, mit AcceptTcpClient()dem auf eine Verbindung gewartet wird. Ein Verweis auf diese Verbindung (sobald sie hergestellt ist) wird in gespeichert $c, in Parens gekapselt und sofort aufgerufen GetStream(), um den Datenstrom abzurufen. Dieser Datenstrom wird an einen neuen System.IO.StreamWriterKonstruktor übergeben $w, damit wir ihn bearbeiten können. Dieser Konstruktor ist selbst in parens gekapselt und wird sofort aufgerufen Write(...).

Innerhalb des Write(...)Anrufs übernehmen wir unseren Kundenhandle $cund erhalten das RemoteEndPointEigentum des Kunden . Dies ist der einzige Weg (den ich bisher gefunden habe), um die entfernte IP-Adresse zu erhalten. Als nächstes müssen wir das als [System.Net.IPEndPoint]Objekt umwandeln, damit es korrekt formatiert ist, das in Parens einkapseln und nur die .AddressEigenschaft ziehen. Wir geben dann -replacedie wörtlichen Punkte mit Pluszeichen ein und leiten sie an Invoke-Expression(ähnlich wie eval) weiter, um unsere Summe zu erhalten.

Nach dem E / A-Schreibvorgang müssen wir einen Aufruf .Dispose()ausführen, um sicherzustellen, dass der Datenstrom an den Client gesendet und geschlossen wird. Der TCP-Server unterbricht die Client-Verbindung ohne Vorwarnung. Abhängig vom verwendeten Client kann es daher zu einem bestimmten Zeitpunkt zu einem Absturz kommen. Anschließend wird die forSchleife durchlaufen , ohne die Verbindungen ordnungsgemäß zu schließen. Dies bedeutet auch, dass es Speicher und Systemhandles wie verrückt verliert, aber das interessiert uns nicht, oder? Möglicherweise müssen Sie den Task-Manager verwenden, um den Prozess abzubrechen, nachdem Sie den Server ausgeführt haben. : D

Auch nur IPv4, da die Summierungsleiste spektakulär versucht, eine IPv6-Adresse zu verarbeiten, da dies :kein gültiger algebraischer Operator iexzum Parsen ist.


2
"Lecks Speicher und System-Handles wie verrückt" Was haben Sie free()sie danach? delete[], vielleicht? : P
cat

8
@tac Ja, es gibt eine ganze Reihe von .close()und .dispose()Methoden wir hier nicht nennen , dass die Menschen auf Code Review verursachen würde einen Sitz haben.
AdmBorkBork

Oh, ist nicht PS GC'd? Oder führt der GC eine Nachzählung durch und keine Scope-Analyse?
Katze

@tac Ja, PowerShell verfügt dank des zugrunde liegenden .NET-Systems über eine Garbage Collection . Abhängig davon, wie Sie dieses Skript aufrufen oder einsetzen, können Sie jedoch auf Fehler wie diesen stoßen, bei denen Speicher in der Pipeline verloren geht. Der obige Code ist auch nicht threadsicher und kann daher zu GC-Problemen führen, da wir den Socket nicht explizit schließen.
AdmBorkBork

1
Beim Testen konnte ich dies nicht zum Laufen bringen, wahrscheinlich aufgrund von Firewall-Problemen, die ich nicht beheben möchte, daher kann ich nicht sicher sein, aber ... Ich denke, Sie können "System" aus den meisten, wenn nicht allen Typumwandlungen entfernen du hast da zB: [Net.ipaddress]::Anyfunktioniert.
Matt

7

PHP 161 (56?)

Dies ist mein erster Beitrag hier. Ich hoffe das geht richtig :)

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

Dies funktioniert nur bei IPV4

Bearbeiten : Ich habe gerade bemerkt, dass PHP Basic Server unterstützt:
Ich habe beschlossen, mich an die ursprüngliche Zeichenanzahl zu halten, es sei denn, jemand bestätigt, ob Folgendes zulässig ist :)

test2.php: (mögliche 56-Byte-Lösung)

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

Und starten Sie den Service mit:

php -S localhost:8080 test2.php

Chrome als Client Bildschirmfoto

Edit 2: wget als Client

$ wget -qO- localhost:8080
128

Ich weiß, Regeln sagen: "Programm oder Funktion liest Integer N aus Argumenten oder stdin", aber ist es in Ordnung, wenn Programm in diesem Fall PHP selbst ist? Oder wird die Verwendung eines eingebauten Servers in PHP als Regelungslücke angesehen?
Mikael

Willkommen bei Programming Puzzles & Code Golf! Ihre 161-Byte-Lösung sieht gut aus. Ist die von Ihnen erwähnte 56-Byte-Lösung die unter test2.php? Wenn ja, müssten Sie das OP fragen, ob diese Art von integriertem System für diese Herausforderung akzeptabel ist. Es ist jedoch keine Lücke.
Alex A.

Ich würde sagen, dass die Verwendung eines eingebauten TCP-Servers akzeptabel wäre, aber in diesem Fall sprechen wir von einem eingebauten HTTP-Server . Die 56-Byte-Lösung 1) unternimmt also nichts, wenn der Client nur eine Verbindung herstellt und nichts sendet. 2) sendet nur "[Wed Mar 30 10:15:02 2016] 127.0.0.1:47974 Invalid request (Malformed HTTP request)" zurück, ohne test2.php auszuführen, falls der Client zum Beispiel "foo" sendet; 3) sendet einen vollständigen Satz von HTTP-Antwort-Headern vor der tatsächlich erforderlichen Antwort, falls der Client eine gültige HTTP-Anfrage sendet.
Manatwork

@ Alex A. Vielen Dank und ja, 56-Byte-Lösung ist unter test2.php :)
Mikael

@manatwork Sie haben Recht, aber ich dachte, dass der Client in dieser Aufgabe nicht klar spezifiziert ist. Ist es in Ordnung, einen Browser oder noch einfacher etwas wie "wget ​​-qO- localhost: 8080" als Client zu verwenden?
Mikael

7

Los , 359 311

Dies ist mein erstes Programm in Go - es erlaubt mir eines zu entdecken: Dies ist definitiv keine gute Golfsprache!

(Ein großes Lob an @ Steve, der den größten Teil des Golfspiels gemacht hat!)

package main
import(n"net";t"strings";r"strconv";x"regexp";"os")
func main(){l,_:=n.Listen("tcp",":"+os.Args[1])
for{c,_:=l.Accept();var s int
for _,i:=range t.Split(x.MustCompile(":[0-9]+$").ReplaceAllLiteralString(c.RemoteAddr().String(),""),"."){
n,_:=r.Atoi(i);s=s+n};c.Write([]byte(r.Itoa(s)));c.Close()}}

2
Aber es ist auf jeden Fall eine schöne Sprache, um einen TCP-Server zu erstellen!
Numeri

1
Seltsamerweise erhalte ich das Ergebnis 360, wenn ich eine Verbindung von 192.168.0.67 herstelle, anstatt von 427.
Steve am

3
Sie können die Pakete strings + strconv benennen, um einige Bytes zu sparen. zB "strings"wird s "strings"so, dass der spätere strings.Splitgerecht wird s.Split.
Steve

1
Ein paar mehr Bytes abrasiert pastebin.com/HY84sazE - angefangen ein bisschen mehr zu suchen „golfed“ jetzt
steve

2
Wenn Sie import(."pkgname")alle Funktionen verwenden, die in den aktuellen Namespace importiert werden, können Sie das Präfix löschen. z.B. import ."fmt"; Println("foo") Wenn Sie Sscanfaus dem fmtPaket die Adresse anstelle von regulären Ausdrücken analysieren, sparen Sie einige weitere Bytes, was Ihnen den netten Vorteil gibt, dass Sie Fprintlndie Gesamtsumme zurückgeben müssen, anstatt sie zu importieren strconv.
Kristoffer Sall-Storgaard

7

Common Lisp, 110 Bytes

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

Einzelheiten

(use-package 'usocket)

(lambda (port)

  ;; create server with event-loop
  (socket-server "localhost"
                 port

                 ;; tcp-handler
                 (lambda (stream)
                   ;; format to stream to client
                   (format stream
                           "~D~%"
                           ;; add all elements of the host,
                           ;; a vector of 4 integers
                           (reduce #'+ *remote-host*))

                   ;; client connection is closed automatically
                   ;; when exiting this function                     
                 )))

2
Yay für gemeines Lithp!
Katze

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: Nimmt das zweite Befehlszeilenargument (das erste "-"soll qnicht Nals Skript / Datei interpretieren ) und öffnet damit einen port ( "p ").
    • Hinweis: Beim Aufrufen wird q -p Nder Port als Nautomatisch festgelegt. Da die Frage jedoch darauf hinzudeuten scheint, dass dies Neher ein Argument für das Programm als für die ausführbare Datei selbst sein sollte, bin ich den längeren Weg gegangen.
  • Enthält in der .z.pgFunktion, die eingehende Anforderungen verarbeitet, .z.adie IP-Adresse als 32-Bit-Ganzzahl.
    • "i"$0x0 vsteilt es in seine ganzzahligen 'Bestandteile' auf und sumführt die Summierung durch.
    • Zuletzt stringdas numerische Ergebnis und hängen Sie "\n"es an, um zum Client zurückzukehren.
  • .z.ph ist eine weitere Funktion für HTTP-GET-Anforderungen mit zusätzlicher Behandlung zum Konvertieren der Zeichenfolgenausgabe in eine gültige HTTP-Antwort.

Demo - Server:

c:\q\w32>q - 1234
KDB+ 3.3 2015.11.03 Copyright (C) 1993-2015 Kx Systems
w32/ 4()core ... NONEXPIRE

Welcome to kdb+ 32bit edition
q)system raze"p ",1_.z.x;.z.pg:{(string sum"i"$0x0 vs .z.a),"\n"};.z.ph:{.h.hy[`;.z.pg[]]}
q)

Demo - Client (von einer anderen qSitzung aus 127.0.0.1):

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

Demo - Kunde (von curl):

$ curl localhost:1234
128

$

6

LiveScript, 107 105 Bytes

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

Es gibt nicht viel hinzuzufügen, es ist nur grundlegendes NodeJS-Zeug. Stilpunkte für &1(zweites Argument), <|(F # $-Piping , ähnlich wie in Haskell) und biop: (+)In LS sind sie wie Operatorabschnitte in Haskell: eine binäre Curry-Funktion (die ihre Operanden hinzufügt). Auch ein bisschen schmutzig: /Wenn rechts davon eine wörtliche Zeichenfolge angegeben wird, wird sie geteilt.


5

Perl, 141 132 + 1 = 133 Bytes

Golf gespielt

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

Beispiel

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

Sind Sie sicher, dass dies korrekt ist? Ich bekomme die Summe auf das Terminal des Servers gedruckt, nicht auf den Client. Auf jeden Fall können Sie alle Klammern entfernen und s/\./+/g→ ändern y/./+/.
Manatwork

Ahh, misread..will entsprechend revidieren und Ihre guten y / Vorschlag einbeziehen.
Steve

1
while(1){…}{…;redo}nach user130144 ‚s großer Spitze . Mit Ausnahme des ->send()Aufrufs sind keine weiteren Klammern erforderlich.
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()

Übernimmt den Hafen über stdin.


4

NodeJS (ES6), 129 118 107 Bytes

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

Funktioniert für IPv4. Rennen wienode server.js <port>


Funktioniert eigentlich nicht, wenn der Server IPv6 verwendet (wie z. B. meiner automatisch), da c.remoteAddressdies dann der Fall wäre ::ffff:127.0.0.1. (Ich habe auf Node v5.9.1 getestet).
Frxstrem

Außerdem haben Sie keine nachgestellte Zeile, wodurch sich Ihre Punktzahl um 2 Byte erhöhen sollte.
Frxstrem

@Frxstrem Hoppla, habe die neue Zeile vergessen. Fügt dank Template-Strings jedoch nur 1 Byte hinzu. In Bezug auf die IP-Familie: .listen()Wird standardmäßig zuerst für IPv4 verwendet, aber es scheint, dass sich dies entweder aufgrund eines Fehlers oder aufgrund des Designs geändert hat. Die Übermittlung funktioniert auf neueren Knotenversionen weiterhin ordnungsgemäß, wenn IPv6 auf dem Hostcomputer deaktiviert ist.
Mwr247

4

Go, 211 Bytes

package main
import(."fmt"
."net"
"os")
func main(){s,_:=Listen("tcp4",":"+os.Args[1])
for{c,_:=s.Accept()
var a,b,d,e int
Sscanf(Sprint(c.RemoteAddr()),"%d.%d.%d.%d",&a,&b,&d,&e)
Fprintln(c,a+b+d+e)
c.Close()}}

Kann wahrscheinlich weiter golfen werden, ich bin nicht ganz zufrieden mit der Art und Weise, wie ich die IP-Adresse zum Beispiel analysieren muss, es sieht aus wie ein schrecklicher Hack.

Lauscht IPv4 auf dem als Argument angegebenen Port.


4

PowerShell, 208 206 192 152 Byte

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

Versionsinformation:

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

Vielen Dank an TimmyD für die Rettung von 14 Bytes!

Ein großes Dankeschön an TessellatingHeckler, der mir 40 Bytes gespart hat


@TimmyD ah hoppla ich habe verpasst, dass das notwendig war ... jetzt behoben
Nacht

Eine Möglichkeit, wie Programme Eingaben vornehmen dürfen, ist stdin. Ich nehme an, diese spezielle Frage spezifiziert das nicht als erlaubt, aber es ist eine allgemeine Code-Golf-Sache, von der ich denke, dass sie für PowerShell zählen sollte. Es unterscheidet sich leider von bash darin, dass es nicht auf Eingaben in stdin wartet, wenn keine bereitgestellt wurden.
Nacht

Fair genug. wieder behoben
Nacht

Okay, jetzt zu einigen Golfspielen - versuchen Sie Folgendes bei 192 -($t=new-object net.sockets.tcplistener($args[0])).start();for(){($z=$t.acceptsocket()).send(($x=[byte[]][char[]](""+($z.remoteendpoint.address-replace"\.","+"|iex))+32),$x.count,0);$z.close()}
AdmBorkBork

1
Ich denke, Sie können dies auf 152 reduzieren - Sie können new-object löschen und direkt umwandeln, die Byte-Array-Konvertierung überspringen und einen String anders umwandeln, $ x überhaupt nicht speichern und die verbleibenden Parameter für send () und es löschen wird ($t=[net.sockets.tcplistener]$args[0]).start();for(){($z=$t.acceptsocket()).send([char[]]"$($z.remoteendpoint.address-replace"\.","+"|iex)");$z.close()}- was ich erst schnell mit netcat verbindung getestet habe, aber es scheint genauso zu funktionieren - trotzdem verbindung von localhost.
TessellatingHeckler

4

8086-Maschinencode (16-Bit-DOS), 163 156 148 148 142 Bytes

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

Äquivalenter Montagecode:

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

Dies setzt voraus ntcpdrv, dass bei INT 0x61(und einem geeigneten Pakettreiber bei 0x60) geladen wird . Kompilieren mit fasm tcpserv.asm.

Es gibt jedoch einige Probleme:

  • Es wird nicht überprüft, ob das Argument eine gültige Portnummer ist oder ob es überhaupt eine Nummer ist.
  • Der Client muss mindestens ein Byte senden, da ich anscheinend keine andere Möglichkeit finde, festzustellen, ob ein Client eine Verbindung hergestellt hat.
  • Es funktioniert nur einmal und hängt bei einem zweiten Versuch. Funktioniert nach einem Neustart wieder.
  • Der zurückgegebene Wert wird mit Nullen aufgefüllt.
  • Dies ist mein allererster Code Golf Eintrag und auch mein allererstes 8086 ASM Programm. Ich bin sicher, dass es Möglichkeiten gibt, dies weiter zu verbessern.

1
Sie können einfach einen Hexdump der kompilierten Ausgabe für 148 Bytes veröffentlichen
cat

Ist das erlaubt Dies würde diesen Eintrag etwas wettbewerbsfähiger machen ...
user5434231

1
Okay, ich habe den Eintrag in Maschinencode geändert. Rasiert auch ein paar Bytes mehr durch Verwenden von xor r,ranstelle von mov r,0.
user5434231

1
Ich habe es auf einer DOS-Maschine geschrieben, auf der es Zeilenumbrüche gibt CR LF, also habe ich mich einfach daran gemacht. So oder so ist es irgendwie sinnlos, die ASM-Größe jetzt zu zählen, sie ein wenig aufzuräumen und einige Kommentare hinzuzufügen.
user5434231

1
Das soll auch hier passieren, und es funktioniert; int 0x61Gibt einen zufälligen lokalen Port in zurück ax. Aber es ändert sich auch die Abhör-IP auf eine 4.2.0.0Müllnummer ( iirc)
user5434231

3

Haskell, 216 Bytes

Verwenden Sie das Paket "network-simple" ( cabal install network-simple). Benötigt ein paar Spracherweiterungen ( -XOverloadedStrings -XNoMonomorphismRestriction), um zu funktionieren.

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)

Es gibt einige mögliche Vereinfachungen, einschließlich der Änderung der wFunktion, um die Summe direkt anstelle einer Liste zurückzugeben, und der Verwendung einer Funktion anstelle eines Programms, damit die Portnummer als Argument angegeben werden kann. Ich kann mir allerdings nicht vorstellen, dass dies die Größe stark reduzieren würde. 20 Bytes vielleicht?


Nett! Ziemlich sicher, dass Sie durch Umbenennen win noch ein paar Bytes sparen können #, was w h nzu h#neiner Einsparung von 2 Bytes pro Nutzung führt.
Actorclavilis

3

Mumps, 114 115 Bytes

Golf gespielt:

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

Dies ist die InterSystems Caché-Version von Mumps - wenn es eine Version gibt, die die TCP-Adresse kürzer als ##class(%SYSTEM.TCPDevice).PeerAddr() (da es fast ein Drittel des gesamten Programms ist) erwerben kann, hat sie möglicherweise eine bessere Chance gegenüber einigen anderen bereits veröffentlichten Sprachen ... ;-)

Edit: Danke an @TimmyD - Ich habe das Lesen des Ports von STDIN oder Argumenten verpasst, anstatt hartcodiert zu werden. Bearbeitet; es fügte dem Programm 1 Byte hinzu.


@TimmyD - Ah, du hast recht. Habe das beim Durchlesen der Anforderungen verpasst. Wird posthaste bearbeiten.
Zmerch

3

C 535 Bytes

Nun, jemand musste das tun.

Ich habe einen einzelnen Zeilenumbruch hinzugefügt, damit der bereitgestellte Code tatsächlich 536 Zeichen enthält.

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

kompilieren mit gcc [file_name] -o server

renn mit ./server [port]

verbinden mit telnet localhost [port]


3
Gute Antwort! Wie bereits erwähnt , können Sie einige Bytes einsparen, indem Sie tatsächliche Werte für einige Konstanten verwenden, z. B. AF_INET und SOCK_STREAM.
Hannes Karppila

2

Java, 210 Bytes

Golf gespielt:

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

Erweitert:

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

Dies ist eine Zusammenstellung aller Tipps, die ich in anderen Java-Antworten gegeben habe, plus das Schreiben als Funktion anstelle eines vollständigen Programms, das im Vergleich zum Programm ungefähr 70 Byte an Umfang gewinnt.


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)

Leider musste ich verwenden Network.Socket, um auf die entfernte IP-Adresse als Ganzzahl anstatt als Zeichenfolge zuzugreifen. Es hätte Dutzende von Charakteren gerettet, wenn ich es nur getan hätte s <- listenOn (PortNumber n), anstatt explizit und individuell anrufen zu socketmüssen . Aber leider gibt mir eine Host- Zeichenfolge , keine Ganzzahl für die IP-Adresse , sodass ich auf und Freunde zurückgreifen musste .bindlistenNetwork.acceptNetwork.Socket.accept

Die Funktion verwendet feine Portnummer als Argument und erstellt einen Server-Socket ( s), der diesen Port überwacht. Anschließend ruft es die Funktion gmit dem Server-Socket auf. gSchleifen für immer, Verbindungen annehmen. Die Funktion verwendet beine tatsächliche IPv4-Adresse und berechnet die Summe ihrer Ziffern.

Ich bin mir sicher, dass irgendjemand das besser kann als ich. Ich wollte zeigen, wie verdammt einfach Socket Zeug in Haskell ist ... aber dann kläglich gescheitert, weil ich Zugriff auf die IP-Adresse, die in der Regel nicht einfach zu bekommen ist.


Das "netzwerk-einfache" Paket bietet eine viel schönere Schnittstelle, die den SockAddr an eine Funktion weitergibt, die Sie ihm geben, was die Dinge einfacher macht. Sehen Sie sich meine Lösung an, die ich gleich veröffentlichen werde ...
Jules

Einige Vereinfachungen sind offensichtlich: (1) Ich glaube, dass dies withSocketsDonur unter Windows erforderlich ist. Wenn Sie also unter Linux laufen, kann es ignoriert werden. (2) 0xFF ist ein längeres Zeichen als 255; (3) Das Konvertieren des Sockets in ein Handle und die Verwendung von normaler E / A ist viel länger als die Verwendung Network.Socket.send. Ja, sendist veraltet, aber der Grund ist für dieses Szenario nicht relevant (er bezieht sich nur auf Nicht-ASCII-Text oder Binärdaten), daher erscheint es sinnvoll, ihn zu verwenden.
Jules

Network.accept gives me a host string, not an IP address integerKönnen nicht spalten Sie den IP - String nur auf das ".", mapdie Ergebnisse Haskells String-to-number - Funktion über den Split - String und zusammenzufassen?
Katze

2

Lua, 169 162 160 153 151 148 138 129 Bytes

Golf Version

m=require"socket".bind(0,...)::l::c=m:accept()f=0 for n in c:getpeername():gmatch"%d+"do f=f+n end c:send(f.."\n")c:close()goto l

Dazu muss Luasocket installiert sein und ein Interpreter, der Labels unterstützt. Ich habe es mit Luajit getestet und kann auch bestätigen, dass der Code mit Lua 5.1 nicht funktioniert.

Ungolfed-Version

m=require"socket".bind(0,...)
::l::
c=m:accept()

f=0
for n in c:getpeername():gmatch"%d+" do
    f=f+n
end
c:send(f.."\n")

c:close()
goto l

Bearbeiten 1:

Geändert i=({c:getpeername()})[1]zu nuri=c:getpeername()

Bearbeiten 2:

Klammern aus der require-Anweisung entfernt.

Edit 3:

Entfernte die geschweiften Klammern um den Vararg und verringerte die Byteanzahl ein wenig.

Bearbeiten 4:

Die Klammer um "% d +", kürzer um 2 Bytes, wurde entfernt.

Edit 5:

Die unnötige Variable i wurde entfernt.

Bearbeiten 6:

Änderte die IP von "127.0.0.1" auf 0. (Danke an xyzzy auf #lua)

Bearbeiten 7:

Der Funktionsaufruf für tonumber wurde entfernt, da Zeichenfolgen automatisch in Zahlen umgewandelt werden. (Vielen Dank an Trebuchette für den Vorschlag, das wusste ich nicht.)


1
Nur Lua 5.2 und höher Support-Labels, wenn Sie neugierig sind
Trebuchette

1
Außerdem wandelt Lua mit dem +Operator automatisch Zeichenfolgen in Zahlen um , sodass Sie sie entfernen können tonumber.
Trebuchette

2

Haskell, 185 (+ 19 = 204)? Bytes

import Network.Simple.TCP(serve)
import Network.Socket
import Data.List.Split
main=getLine>>=flip(serve"*4")(\(a,b)->()<$(send a$(++"\n")$show$sum.map read.take 4.sepByOneOf":."$show b)

Nimmt die Portnummer als eine Zeile auf stdin; benötigt network-simplevon Cabal.

Wie bei Haskell-Antworten üblich, die sich nicht auf reine Funktionen beschränken, importsbelegen sie viel zu viele Bytes. Die abschließende Newline ist ebenfalls 9 Bytes wert ...

Etwas ähnlich der Antwort von @ Jules, aber ich verwende eine Zeichenkettenmanipulation anstelle von Byteoperationen. Ich habe auch die -XOverloadedStringsErweiterung benutzt, die wahrscheinlich 19 Bytes mehr wert ist.


2

C, 243 188 Bytes (oder vielleicht 217 162 Bytes)

V2: Erläuterungen siehe unten.

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

162 Bytes leicht überschauen:

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

Möglicherweise ist morgen früh mehr Golf möglich. Ich werde diesen Beitrag nach diesen Updates aufräumen.


V1:

Dieser hat wirklich Spaß gemacht, Golf zu spielen.

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

Es funktioniert für IPv4. Meist ist es eine einfache Implementierung. Die drei Hauptkomponenten sind

Socket erstellen:

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

Wir verwenden die verschiedenen expliziten Formen der Konstanten AF_INET usw. und machen uns die Tatsache zunutze, dass bei einer solchen Initialisierung einer Struktur in C die nicht spezifizierten Elemente auf Null gesetzt werden.

Hören Sie auf Kunden, akzeptieren Sie sie und schließen Sie ihre Verbindungen:

for (listen (s, 8); c = accept (s, & C, & g); q = fclose (g))

Zum Schluss senden Sie jedem Kunden die Daten:

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

Die IP wird C.sin_addr.s_addrals 32-Bit-Ganzzahl gespeichert, wobei jedes Oktett durch eines der vier Bytes dargestellt wird. Wir addieren diese Bytes mit der for-Schleife und drucken sie dann mit fprintf in den Stream.

Ich habe eine kürzere 217-Byte-Lösung, bin mir aber nicht ganz sicher, ob sie nicht gegen die Standard-Regelungslücken verstößt, da der Port in der Reihenfolge der Netzwerkbytes als Befehlszeilenargumente unär angegeben werden muss. Das heißt, um den Server auf Port 12345 auszuführen, müsste man anrufen

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

wo die Gesamtzahl von 1s 14640 ist. Um es gelinde auszudrücken, ist es ein wenig ... umständlich. Aber hier ist es trotzdem:

#include<netdb.h>
s,c,q;main(g){struct sockaddr_in S={2,g},C;bind(s=socket(2,1,0),&S,g=16);for(listen(s,8);c=accept(s,&C,&g);q=fclose(g)){for(g=4;g;q+=C.sin_addr.s_addr>>8*--g&255);fprintf(g=fdopen(c,"w"),"%d\n",q);}}

2

Schläger, 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)))

2

Faktor 155 146 131 206 190 Bytes

Nun, ich habe gerade viel über Low-Level-Socket-Programmierung gelernt. Ich glaube nicht , dass ich jemals tun wollen , dass wieder, weil mein thr Kopf tut weh.

[ 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 ja, Threaded, und kommt nicht zurück, richtig.


Können Sie 10 base>anstelle von verwenden string>number?
fede s.

@fedes. Wow, ich wusste nie, dass es das gibt. Ich denke, das wird es mir ermöglichen, viele meiner Faktor-Antworten zu verkürzen!
Katze

Und 10 >basefür number> string auch.
fede s.

1
@fedes. Diejenigen verdienen eine Antwort hier : D
Katze
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.