Server TCP sederhana


104

Tulis program atau fungsi yang mendengarkan lalu lintas TCP yang masuk pada port N. Ini menawarkan layanan sederhana: menghitung jumlah bidang alamat IP dari koneksi yang masuk dan kembali.

Program atau fungsi membaca integer N dari argumen atau stdin. Ia mendengarkan koneksi TCP yang masuk pada port N. Ketika seseorang terhubung ke port itu, program menghitung jumlah bidang alamat IP-nya dan mengirimkannya kembali ke klien dengan mengikuti baris baru dan menutup koneksi.

  • Nomor port N adalah port yang valid, dan 2 10 <N <2 15
  • Mengejar baris baru dapat berupa \natau\r\n
  • Anda dapat menggunakan IPv4 atau IPv6. Karena alamat IPv6 ditulis dalam bentuk heksadesimal, Anda juga harus memberikan hasil dalam format yang sama, misalnya 2001:0db8:0000:0042:0000:8a2e:0370:7334 => 12ecd.

Ini adalah . Aturan dan celah standar berlaku.

Contoh

Anda menjalankan server Anda dengan ./server 1234. Server sekarang sedang berjalan dan menunggu koneksi pada port 1234. Kemudian klien dari 127.0.0.1terhubung ke server Anda. Server Anda melakukan perhitungan sederhana: 127+0+0+1 => 128dan mengirimkan hasilnya ke klien (dengan newline yang mengekor): 128\n. Kemudian server menutup koneksi dan menunggu klien berikutnya.

Papan peringkat

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
Apakah diizinkan menggunakan inetd / xinetd atau serupa?
Digital Trauma

91
Saya suka ini, karena ini adalah tantangan golf yang tidak mungkin dilakukan oleh bahasa golf.
isaacg

9
Tidak hanya menakjubkan bahwa server TCP tampaknya adalah program yang sangat mudah untuk ditulis, saya benar-benar didasarkan pada kenyataan bahwa itu menjadi golf untuk bersenang-senang. Saya hanya akan kembali berjuang dengan FizzBuzz seperti orang dungu.
MonkeyZeus

17
@isaacg Hanya perlu waktu sebelum seseorang menemukan server TCP built-in di Mathematica
Downgoat

3
@MonkeyZeus Agar adil, Anda tidak akan melihat server TCP yang baik di sini. Membuat server TCP yang andal dan dapat diskalakan yang menangani semua seluk-beluk TCP (dan protokol aplikasi Anda) dengan baik agak sulit: D Meskipun tentu saja membantu bahwa protokolnya sangat sederhana - Anda bahkan tidak perlu membaca streaming, sesuatu yang saya lihat rusak di terlalu banyak server TCP untuk dihitung: D
Luaan

Jawaban:


57

Bash + netcat + ss +…, 65 60 karakter

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

Bukan solusi serius, hanya penasaran dengan kemungkinan ini.

Terimakasih untuk:

  • ninjalj untuk menyarankan awkpemfilteran berbasis (-5 karakter)

Contoh dijalankan:

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

Di Ubuntu Anda bisa dapatkan ncdari netcat-tradisional (tidak, netcat-openbsd tidak bagus) dan ssdari iproute2 .


22
Mengapa Anda mengatakan itu bukan solusi serius? Selama itu berfungsi seperti yang diharapkan, saya tidak melihat alasan mengapa itu tidak dianggap serius. Ini juga terpendek dengan margin yang cukup signifikan saat ini.
Alex A.

Kekhawatiran terbesar terhadap hal itu muncul selama diskusi dengan @JesseSielaff ketika saya mengetahui bahwa pada sistem dengan konfigurasi IPv6, informasi terkait soket mungkin diformat secara berbeda. Tidak memiliki sistem untuk mengujinya. Untuk itulah saya berpikir apakah akan lebih benar mengubahnya menjadi CW.
manatwork

3
Pemahaman saya tentang spec adalah bahwa Anda harus mendukung IPv4 atau IPv6, tidak keduanya. Jadi selama itu bekerja untuk IPv4, tidak mendukung IPv6 seharusnya tidak masalah, saya akan berpikir.
Alex A.

1
@AlexA. Setidaknya saya pikir pertanyaan saya mengatakan demikian. Haruskah saya menjelaskannya?
Hannes Karppila

@ HannesKarppila, pertanyaan Anda jelas. Masalah yang mungkin terjadi adalah solusi saya mungkin memerlukan sistem operasi untuk dikonfigurasikan dengan cara tertentu agar dapat dijalankan. Jadi saya khawatir karena mungkin gagal jika IPv6 dikonfigurasi, terlepas dari apakah saya menanganinya atau tidak. Seseorang yang memiliki konfigurasi IPv6 dapat memastikannya ...
manatwork

23

C #, 284 283 282 278 274 254 byte

class A{static int Main(string[]a){var b=new System.Net.Sockets.TcpListener(int.Parse(a[0]));b.Start();for(;;){var c=b.AcceptTcpClient();var d=c.Client.LocalEndPoint.Serialize();new System.IO.StreamWriter(c.GetStream()).WriteLine(d[4]+d[5]+d[6]+d[7]);}}}

Contoh klasik dari server C # TCP dasar. Pengujian:

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:


7
Anda dapat menyimpan 1 Byte dengan menggunakan int Mainalih-alih void Main. Karena program tidak pernah mengembalikan kompiler tidak memerlukan returnpernyataan.
raznagul

Dan tidak, itu tidak bocor. Ini sebenarnya cukup deterministik tentang pelepasan sumber daya juga. Juga, argumennya Startadalah opsional, menyimpan karakter lain.
Luaan

@Luaan Ya, yang tersisa dari debugging.
LegionMammal978

Selain itu, Anda dapat menggunakan usingpada TcpClient, yang akan menyelamatkan Anda tiga karakter lagi (gunakan {}dari for), dan melakukan hal yang sama dengan StreamWriterharus menyimpan satu lagi.
Luaan

@Luaan Saya perlu secara eksplisit Flushdalam StreamWriteruntuk membuatnya bekerja dengan baik.
LegionMammal978

22

Linux ELF / x86, 146 byte

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

Termasuk header 52-byte ELF, header program 32-byte, 111 byte kode program + 3 byte kode untuk dilewati di dalam header.

Informasi tentang cara membuat executable ELF yang kecil dapat ditemukan di breadbox 's " A Whirlwind Tutorial tentang Menciptakan ELF Executables ELF yang Benar-benar Cukup untuk Linux " .

Linux / i386 menggunakan socketcall(2)panggilan sistem multipleks, yang mengambil ebxpanggilan soket khusus ( SYS_*makro dari /usr/include/linux/net.h), dan dalam ecxpointer ke area argumen panggilan perpustakaan asli.

Beberapa hal dilakukan untuk menjaga eksekusi kecil:

  • Ini mengasumsikan register memusatkan perhatian pada entri, yang Linux lakukan, tetapi tidak diharuskan oleh standar ELF (satu-satunya persyaratan adalah bahwa pada EDXtitik masuk ke funtion finalisasi (berguna untuk executable yang dimuat oleh dynamic linker) atau NULL).
  • Ini mengasumsikan pada peluncuran (biasanya oleh shell) satu-satunya deskriptor file yang terbuka adalah 0, 1, dan 2. Yang berarti bahwa soket pendengaran akan menjadi fd 3, dan soket yang diterima akan menjadi fd 4.
  • Diasumsikan ada tepat 2 argumen (termasuk argv[0]).
  • Ruang stack yang sama digunakan kembali untuk panggilan bind(2), listen(2)dan accept(2).
  • Untuk melewati phentsizedan phnumbidang, byte digantikan, berubah menjadi CMPoperasi yang mengambil bidang phentsizedan phnumsebagai langsung (trik tanpa malu dicuri dari solusi breadbox ke 123 di golf anarki ).
  • operasi string x86 LODS(memuat ke akumulator dan indeks sumber kenaikan / penurunan) dan STOS(menyimpan dari akumulator dan indeks tujuan kenaikan / penurunan) bagus untuk kode pendek.
  • XCHG EAX, regadalah 1-byte, dibandingkan dengan MOV EAX, reg, yang membutuhkan 2 byte.
  • CDQ/CLTD(sign-extended EAXke EDX:EAX) dapat digunakan sebagai cara 1-byte untuk nol EDXregister.
  • BSWAPberguna untuk implementasi htons().

Sumber nasm:

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

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

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

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

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

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

4
Jawaban ini kurang dihargai.
kucing

16

NodeJS, 146 134 127 byte

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

Saya akhirnya bisa mengirim jawaban NodeJS! IPv4 hanya sekarang.

Eksekusi sampel: node script.js 1024. Dari terminal lain:

$ curl 127.0.0.1:1024
128

2
Saya menghitung 127 byte sekarang, meskipun Anda bisa turun ke 126 dengan bertukar '\n'dengan string template yang berisi baris baru literal.
Mwr247

Bukankah ini gagal persyaratan karena Anda membuat server HTTP, maksud saya, ini secara teknis server TCP, tetapi tidak bisakah Anda menggunakan modul TCP dan menyelamatkan karakter?
MayorMonty

14

Tcl, 92

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

Cukup jelas:

socket -server s $argv membuat soket pendengaran pada port yang ditentukan dalam argumen.

Setiap kali koneksi baru tiba, proc situ disebut, dengan saluran, alamat-sumber dan port-sumber sebagai parameter. string mappengganti .untuk +di alamat sumber, dan exprderet hitung mengevaluasi hasil, yang kemudian putskembali ke saluran koneksi c.

vwait menjalankan loop acara untuk menangkap acara koneksi yang masuk.


Kredit ke @ DonalFellows untuk yang berikut:

Berikut adalah versi yang menangani IPv6 (membutuhkan Tcl 8.6; sebagian besar panjang tambahan adalah karena menghasilkan respons hex):

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
Menggunakan applytampaknya tidak menyimpan sesuatu. Anda juga tidak dapat menggunakan tcl::mathop::+ {*}[split $a .]karena itu sedikit lebih lama. Anda juga tidak dapat mencukur apa pun dari nama opsi. Tetapi mendukung IPv6 cukup sepele untuk ditambahkan, dan hanya membutuhkan biaya beberapa byte kode lebih banyak (dan kemudian regsubpendekatan berbasis sama selama).
Donal Fellows

ahhh, Tcl / Tcl-DP ... alat yang luar biasa. (pada tahun 90-an seorang profesor menunjukkan kepada kami bahwa kami dapat menulis Excel yang didistribusikan jaringan (dengan kisi-kisi, dan termasuk evaluasi rumus!) dibagikan di antara beberapa orang dengan (iirc) 4 baris (pendek) untuk server dan 5 untuk klien. ..
Olivier Dulac

proc s {c a p}apakah Anda benar-benar membutuhkan semua spasi putih itu?
kucing

12

Groovy 133 , 125 , 93 , 89

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

Hanya IPv4, mungkin.

Tidak Disatukan:

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

Pengujian:

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

1
.toInteger()as intdan s.inetAddress.address*.toInteger()(s.inetAddress.address as int[]). Dan ada ruang ekstra setelahnya .with.
manatwork

@manatwork thx! Diperbarui.
Will Lp

9

Python 3, 170 166 147 byte

from socket import*
s=socket()
s.bind(("",int(input())))
s.listen()
while 1:
 c,a=s.accept()
 c.send(b"%d\n"%eval(a[0].replace(".","+"))),c.close()

Mengambil port aktif stdin, hanya IPv4. Bekerja pada GNU / Linux (dan, saya berasumsi, sebagian besar unix lainnya), yang secara otomatis memperluas "" ke "0.0.0.0", tidak yakin tentang Windows.


2
Anda dapat menyimpan beberapa byte. Pertama, spasi di import *dan , SOCK_STREAMtidak perlu. Juga, baris kirim dapat ditulis lebih efisien sebagai c.send(b"%d\n"%eval(a[0].replace(".","+"))).
Hannes Karppila

2
@ HannesKarppila oh, terima kasih. lupa tentang spasi, hack eval cukup keren.
sammko

2
AF_INET dan SOCK_STREAM hanyalah konstanta; AF_INET adalah 2 dan SOCK_STREAM adalah 1. Juga, seperti yang disebutkan, SOCK_STREAM tidak perlu; sehingga Anda dapat mempersingkat dengan menggunakan s=socket(2).
Skyler

1
tidak bisakah Anda melakukan socket () dan karena itu menyimpan byte lain?
Foon

1
Anda dapat menyimpan 10 karakter dengan menggunakan Python 2. Kemudian, int(input())menjadi input()dan bagian kirim menjadic.send(`eval(a[0].replace(".","+"))`)
Blender

9

Java, 371 368 350 344 333 310 295 282 byte

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

Tidak disatukan

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

Keluaran

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

1
Lepaskan int k=dan ganti k dengan semua hal di dalamnya Integer.toString(k). Untuk menyimpan beberapa byte.
GiantTree

1
Byte Javas cukup yakin mengacaukan nilai kembali untuk 192.168.2.1 atau alamat serupa dengan byte di atas 127.
AlexR

1
Ubah interfaceuntuk classmendapatkan beberapa byte lagi
ortis

2
Gunakan a.getOutputStream().write((c[0] + c[1] + c[2] + c[3]+"\n").getBytes());sebagai gantinew DataOutputStream(a.getOutputStream()).writeBytes(c[0] + c[1] + c[2] + c[3] + "\n")
ortis

3
Bukankah try(Socket a=...){}lebih pendek dari itu a.close();? Membutuhkan Java 7, tetapi bisa mendapatkan byte.
Olivier Grégoire

8

PowerShell v2 +, 303 268 257 227 byte

nal n new-object;($l=n Net.Sockets.TcpListener($args[0])).Start()
for(){($w=n IO.StreamWriter(($c=$l.AcceptTcpClient()).GetStream())).Write((([Net.IPEndPoint]$c.Client.RemoteEndPoint).Address-replace"\.",'+'|iex))
$w.Dispose()}

Menyimpan 35 byte berkat Matt ... Menyimpan 11 byte lainnya dengan aliasing New-Objectdan minor tweak ... Menyimpan 30 byte lebih banyak dengan secara implisit menggunakan localhost alih-alih anyalamat IP dan dikoreksi ke akun untuk penggunaan berkelanjutan seperti yang ditentukan sebelumnya dan saya tidak terjawab

Sangat mirip dengan jawaban C # , karena .NET yang mendasari keduanya. Kami menyimpan beberapa byte di sini di atas jawaban C # dengan dapat memanfaatkan fungsionalitas PowerShell yang kembali (mengelilingi deklarasi / penugasan kami di parens, dan kemudian segera memanggil metode.), Tetapi kami kehilangan banyak hal karena harus merumuskan penjumlahan . Fakta bahwa kami mendapat nama / panggilan kelas yang sedikit lebih pendek adalah mengapa jawaban ini mengalahkan C #.

Penjelasan

Kami pertama-tama membuat New-Alias(dengan nalalias) untuk menghemat pengetikan ulang New-Objectnanti. Sisa dari baris pertama adalah menyiapkan TCP Listener. Kami melewati baris perintah $args[0]sebagai input untuk membuat yang baru System.Net.Sockets.TcpListener, disimpan sebagai $l. Objek itu dienkapsulasi dalam parens dan segera dipanggil dengan .Start()agar aktif membuka soket.

Memasuki forloop tak terbatas , kami kemudian mengatur pendengar kami $luntuk memblokir AcceptTcpClient()yang akan menunggu koneksi. Referensi ke koneksi itu (setelah dibuat) disimpan dalam $c, dienkapsulasi dalam parens, dan segera dipanggil GetStream()untuk mendapatkan datastream. Datastream itu diteruskan ke System.IO.StreamWriterkonstruktor baru $w,, jadi kita bisa memanipulasinya. Konstruktor itu sendiri diringkas dalam parens dan segera dipanggil Write(...).

Di dalam Write(...)panggilan, kami menangani klien kami $cdan mendapatkan RemoteEndPointproperti klien . Ini adalah satu-satunya cara (yang saya temukan sejauh ini) untuk mendapatkan alamat IP jarak jauh. Selanjutnya kita perlu melemparkan kembali itu sebagai [System.Net.IPEndPoint]objek sehingga diformat dengan benar, merangkumnya dalam parens, dan menarik hanya .Addressproperti. Kami kemudian -replaceperiode harfiah dengan tanda-tanda plus, kemudian pipa itu ke Invoke-Expression(mirip dengan eval) untuk mendapatkan penjumlahan kami.

Setelah IO menulis, kita perlu menelepon .Dispose()untuk memastikan datastream memerah ke klien dan ditutup. Server TCP menjatuhkan koneksi klien tanpa peringatan, jadi tergantung pada klien yang digunakan, mungkin hang untuk sementara waktu pada saat ini. Kemudian dilanjutkan melalui forloop tanpa menutup koneksi dengan benar. Ini juga berarti itu bocor memori dan sistem menangani seperti orang gila, tapi kami tidak peduli tentang itu, kan? Anda mungkin perlu menggunakan Task Manager untuk mematikan proses ketika Anda selesai menjalankan server. : D

Juga hanya IPv4, karena penjumlahan barfs secara spektakuler mencoba menangani alamat IPv6, karena :bukan operator aljabar yang valid untuk iexmelakukan parsing.


2
"Kebocoran memori dan sistem menangani seperti orang gila" Apa, apa yang Anda miliki free()setelah itu? delete[], mungkin? : P
cat

8
@tac Ya, ada banyak sekali .close()dan .dispose()metode yang tidak kami panggil di sini yang akan menyebabkan orang-orang di Code Review cocok.
AdmBorkBork

Oh, bukankah PS GC? Atau apakah GC melakukan penghitungan ulang dan bukan ruang lingkup analisis?
kucing

@tac Ya, PowerShell memang memiliki pengumpulan sampah berkat sistem .NET yang mendasarinya. Tetapi, tergantung pada bagaimana Anda memanggil atau memanfaatkan skrip ini, Anda dapat mengalami bug seperti ini yang membocorkan memori di dalam pipa. Kode di atas juga tidak aman untuk thread, sehingga dapat mengalami masalah GC dengan itu, karena kita tidak secara eksplisit menutup soket.
AdmBorkBork

1
Dalam pengujian saya tidak bisa mendapatkan ini berfungsi, kemungkinan karena masalah firewall yang saya tidak merasa ingin memperbaikinya jadi saya tidak yakin tapi ..... Saya pikir Anda dapat menghapus "Sistem" dari kebanyakan jika tidak semua tipe gips Anda ada di sana yaitu: [Net.ipaddress]::Anybekerja.
Matt

7

PHP, 161 (56?)

Ini posting pertama saya di sini. Saya harap ini berjalan dengan benar :)

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

Tidak Disatukan:

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

Ini hanya berfungsi untuk IPV4

Sunting : Saya baru saja memperhatikan bahwa php mendukung server dasar:
Saya memutuskan untuk tetap berpegang pada jumlah karakter asli kecuali seseorang mengonfirmasi jika yang berikut diperbolehkan :)

test2.php: (kemungkinan solusi 56-byte)

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

Dan kemudian mulai layanan dengan:

php -S localhost:8080 test2.php

Chrome sebagai klien tangkapan layar

Sunting 2: wget sebagai klien

$ wget -qO- localhost:8080
128

Saya tahu aturan mengatakan: "Program atau fungsi membaca integer N dari argumen atau stdin", tetapi apakah boleh jika program dalam hal ini adalah php itu sendiri? Atau apakah menggunakan server builtin di php dianggap sebagai celah?
Mikael

Selamat Datang di Programming Puzzles & Code Golf! Solusi 161 byte Anda tampak hebat. Apakah solusi 56-byte yang Anda sebutkan di bawah test2.php? Jika demikian, saya pikir Anda harus bertanya kepada OP apakah mereka akan menganggap built-in seperti itu dapat diterima untuk tantangan ini. Tapi itu bukan celah.
Alex A.

Saya akan mengatakan, menggunakan server TCP builtin akan dapat diterima, tetapi dalam hal ini kita berbicara tentang server HTTP builtin . Jadi solusi 56 byte 1) tidak melakukan apa-apa jika klien hanya menghubungkan dan mengirim apa-apa; 2) hanya mengirim kembali “[Rab 30 Mar 10:15:02 2016] 127.0.0.1:47974 Permintaan tidak valid (Permintaan HTTP salah)” tanpa menjalankan test2.php jika klien mengirim misalnya “foo”; 3) mengirim set lengkap header respons HTTP sebelum respons yang diperlukan sebenarnya jika klien mengirim permintaan HTTP yang valid.
manatwork

@Alex A. Terima kasih dan ya, solusi 56-byte berada di bawah test2.php :)
Mikael

@manatwork Anda benar tetapi saya berpikir bahwa klien tidak ditentukan dengan jelas dalam tugas ini. Jadi apakah boleh menggunakan browser atau bahkan sesuatu yang lebih simpel seperti "wget ​​-qO- localhost: 8080" sebagai klien?
Mikael

7

Pergi , 359 311

Ini adalah program pertama saya di Go - Ini memungkinkan saya menemukan satu hal: Ini jelas bukan bahasa golf yang bagus!

(Kudos kepada @steve yang melakukan sebagian besar golf!)

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

2
Tapi itu pasti bahasa yang bagus untuk membuat server tcp!
Numeri

1
Aneh, saya mendapatkan hasilnya 360 ketika saya terhubung dari 192.168.0.67, bukan 427.
steve

3
Anda bisa memberi nama paket strings + strconv untuk menyimpan beberapa byte. misalnya "strings"menjadi s "strings"sehingga nanti strings.Splitmenjadi adil s.Split.
steve

1
Lebih sedikit byte dipotong dari pastebin.com/HY84sazE - mulai terlihat sedikit lebih "golf" sekarang
steve

2
Jika Anda menggunakan import(."pkgname")semua fungsi yang akan diimpor ke namespace saat ini, Anda dapat menjatuhkan awalan. misalnya. import ."fmt"; Println("foo") Jika Anda menggunakan Sscanfdari fmtpaket untuk mem-parsing alamat alih-alih regex, itu akan menghemat beberapa byte lagi, memberi Anda bonus bagus Fprintlnuntuk mengembalikan total alih-alih mengimpor strconv.
Kristoffer Sall-Storgaard

7

Gangguan Umum, 110 byte

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

Detail

(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 untuk Lithp Umum!
kucing

6

q, 88 byte

system raze"p ",1_.z.x;.z.pg:{(string sum"i"$0x0 vs .z.a),"\n"};.z.ph:{.h.hy[`;.z.pg[]]}
  • system raze"p ",1_.z.x: Mengambil argumen baris perintah kedua (yang pertama "-"adalah untuk mengatakanq agar tidak menafsirkan Nsebagai skrip / file) dan membuka port ( "p ") dengannya.
    • Catatan: Panggilan q -p Nmenetapkan porta sebagaiN secara otomatis, tetapi karena pertanyaan itu tampaknya menyarankan bahwa Nseharusnya menjadi argumen untuk program daripada eksekusi itu sendiri, saya sudah melangkah lebih jauh.
  • Di dalam .z.pg fungsi yang menangani permintaan masuk, .z.amemegang alamat IP sebagai integer 32-bit.
    • "i"$0x0 vsmembaginya menjadi 'konstituen' integernya, dan summelakukan penjumlahan.
    • Terakhir, stringhasil numerik dan ditambahkan "\n"ke sana untuk kembali ke klien.
  • .z.ph adalah fungsi lain untuk permintaan HTTP GET, dengan penanganan ekstra untuk mengubah output string menjadi respons HTTP yang valid.

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 - Klien (dari qsesi lain yang berjalan pada 127.0.0.1):

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

Demo - Klien (dari curl):

$ curl localhost:1234
128

$

6

LiveScript, 107 105 byte

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

Tidak banyak yang bisa ditambahkan, itu hanya hal-hal dasar NodeJS. Poin gaya untuk &1(argumen kedua), <|(F # perpipaan, mirip dengan $di Haskell) dan biop: (+)di LS seperti bagian operator di Haskell: fungsi biner kari (yang menambahkan operannya). Juga agak kotor:, /jika diberi string literal di sebelah kanannya, akan melakukan split.


5

Perl, 141 132 + 1 = 133 byte

Golf

$s=new IO::Socket::INET LocalPort=><>,Listen=>5,Reuse=>1;{$c=$s->accept;$_=$c->peerhost;y/./+/;$c->send(eval.$/);shutdown $c,1;redo}

Tidak disatukan

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

Contoh

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

Apakah Anda yakin ini benar? Saya mendapatkan jumlah yang dicetak di terminal server, bukan di klien. Bagaimanapun, Anda dapat menghapus semua tanda kurung dan mengubah s/\./+/gy/./+/.
manatwork

Ahh, salah baca .. akan merevisi sesuai dan memasukkan y / saran baik Anda.
steve

1
while(1){…}{…;redo}menurut tip yang bagus dari user130144 . Dan kecuali panggilan, semua tanda kurung lainnya tidak perlu. ->send()
manatwork

4

Python 2, 180 byte

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

Mengambil port over stdin.


4

NodeJS (ES6), 129 118 107 byte

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

Bekerja untuk IPv4. Jalankan sebagainode server.js <port>


Sebenarnya tidak berfungsi jika server menggunakan IPv6 (seperti, misalnya, milik saya secara otomatis), karena itu c.remoteAddressakan menjadi ::ffff:127.0.0.1. (Saya menguji pada Node v5.9.1).
Frxstrem

Selain itu, Anda tidak memiliki trailing newline, yang seharusnya meningkatkan skor Anda sebesar 2 byte.
Frxstrem

@Frxstrem Whoops, lupa baris baru itu. Hanya menambahkan 1 byte meskipun berkat string template. Mengenai keluarga IP: .listen()dulu default ke IPv4, tetapi tampaknya oleh bug atau desain bahwa ini telah berubah. Pengajuan masih akan berfungsi dengan baik pada versi node yang lebih baru ketika IPv6 dinonaktifkan pada mesin host.
Mwr247

4

Pergi, 211 byte

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

Mungkin bisa bermain golf lebih lanjut, saya tidak sepenuhnya puas dengan cara saya harus mengurai alamat IP misalnya, sepertinya hack yang mengerikan.

Mendengarkan IPv4 pada port yang diberikan sebagai argumen.


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

informasi versi:

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

Terima kasih kepada TimmyD karena telah menyelamatkan saya 14 byte!

Terima kasih banyak kepada TessellatingHeckler karena telah menyelamatkan saya 40 byte


@TimmyD ah oops, aku merindukan bahwa itu perlu ... diperbaiki sekarang
Nacht

Salah satu cara program diizinkan untuk mengambil input adalah dari stdin. Saya kira pertanyaan khusus ini tidak menentukan bahwa sebagaimana diperbolehkan tetapi itu adalah hal golf-kode umum yang saya pikir harus dihitung untuk PowerShell. Sayangnya berbeda dari bash karena tidak menunggu input pada stdin jika belum ada yang diberikan.
Nacht

cukup adil. diperbaiki lagi
Nacht

Baiklah, sekarang untuk beberapa golf - coba yang berikut di 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
Saya pikir Anda dapat mengetuk ini ke 152 - drop-objek baru dan dilemparkan langsung, lewati konversi byte array dan lakukan string cast berbeda, jangan menyimpan $ x sama sekali dan drop parameter yang tersisa untuk mengirim (), dan itu menjadi ($t=[net.sockets.tcplistener]$args[0]).start();for(){($z=$t.acceptsocket()).send([char[]]"$($z.remoteendpoint.address-replace"\.","+"|iex)");$z.close()}- yang saya baru saja diuji dengan cepat dengan menghubungkan netcat, tetapi tampaknya berfungsi sama - tetap terhubung dari localhost.
TessellatingHeckler

4

8086 kode mesin (16-bit DOS), 163 156 148 148 142 byte

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

Kode perakitan yang setara:

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

Asumsi ntcpdrvini dimuat di INT 0x61(dan driver paket yang sesuai di 0x60). Kompilasi dengan fasm tcpserv.asm.

Ini memiliki beberapa masalah:

  • Itu tidak memeriksa apakah argumen itu nomor port yang valid, atau apakah itu bahkan nomor.
  • Klien harus mengirim setidaknya satu byte, karena saya tidak bisa menemukan cara lain untuk mengetahui apakah klien telah terhubung.
  • Ini hanya berfungsi sekali, dan hang pada upaya kedua. Bekerja lagi setelah reboot.
  • Nilai yang dikembalikan kiri-diisi dengan nol.
  • Ini adalah entri golf kode pertama saya, dan juga program as86 8086 pertama saya. Saya yakin ada cara untuk meningkatkan ini lebih lanjut.

1
Anda bisa memposting hexdump dari output yang dikompilasi untuk 148 byte
cat

Apakah itu diizinkan? Ini akan membuat entri ini sedikit lebih kompetitif ...
user5434231

1
Baiklah, saya telah mengubah entri ke kode mesin. Juga mencukur beberapa byte lagi dengan menggunakan xor r,rbukan mov r,0.
user5434231

1
Saya menulisnya di mesin dos di mana baris baru CR LF, jadi saya hanya pergi dengan itu. Either way agak tidak ada gunanya untuk menghitung ukuran asm sekarang, mungkin juga membersihkannya sedikit dan menambahkan beberapa komentar.
user5434231

1
Itu seharusnya terjadi di sini juga, dan itu berhasil; int 0x61mengembalikan port lokal acak dalam ax. Tetapi itu juga mengubah IP yang mendengarkan ke beberapa nomor sampah ( 4.2.0.0iirc)
user5434231

3

Haskell, 216 byte

Menggunakan paket "network-simple" ( cabal install network-simple). Perlu beberapa ekstensi bahasa ( -XOverloadedStrings -XNoMonomorphismRestriction) untuk berfungsi.

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)

Ada beberapa kemungkinan penyederhanaan, termasuk mengubah wfungsi untuk mengembalikan jumlah secara langsung daripada daftar, dan menggunakan fungsi daripada program sehingga nomor port dapat ditentukan sebagai argumen. Saya tidak membayangkan ini akan mengurangi ukuran sangat banyak. 20 byte mungkin?


Bagus! Cukup yakin Anda masih dapat mencukur beberapa byte dengan mengubah nama wmenjadi #, jadi w h nmenjadi h#npenghematan 2 byte per penggunaan.
Actorclavilis

3

Mumps, 114 115 Bytes

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}

Tidak Disatukan:

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

Ini adalah versi InterSystems Caché dari Mumps - jika ada versi di luar sana yang dapat memperoleh alamat TCP lebih pendek dari ##class(%SYSTEM.TCPDevice).PeerAddr() (karena hampir 1/3 dari seluruh program) mungkin ada peluang lebih baik terhadap beberapa bahasa lain yang sudah diposting ... ;-)

Sunting: Terima kasih kepada @TimmyD - Saya melewatkan pembacaan port dari STDIN atau argumen alih-alih hardcoded. Diedit; itu menambahkan 1 byte ke program.


@ TimmyD - Ah, Anda benar. Ketinggalan saat membaca persyaratan. Akan mengedit posthaste.
zmerch

3

C, 535 byte

Ya, seseorang harus melakukan ini.

Saya menambahkan satu baris jeda sehingga kode yang diposting sebenarnya memiliki 536 karakter.

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

kompilasi dengan gcc [file_name] -o server

jalankan bersama ./server [port]

terhubung dengan telnet localhost [port]


3
Jawaban bagus! Seperti disebutkan sebelumnya , Anda dapat menyimpan beberapa byte dengan menggunakan nilai aktual untuk beberapa konstanta, seperti AF_INET dan SOCK_STREAM.
Hannes Karppila

2

Java, 210 byte

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

Diperluas:

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

Ini adalah kumpulan dari semua tips yang saya berikan di jawaban Java lainnya, ditambah tulisan sebagai fungsi alih-alih program penuh, yang mendapatkan sekitar 70 byte dibandingkan dengan program.


2

Haskell, 326 byte

import Data.Bits
import Network.Socket
import System.IO
f n=withSocketsDo$do
 s<-socket AF_INET Stream defaultProtocol
 bind s$SockAddrInet n iNADDR_ANY
 listen s 1
 g s
g s=do
 (z,SockAddrInet _ a)<-accept s
 h<-socketToHandle z WriteMode
 hPutStrLn h$show$b a
 hClose h
 g s
b 0=0
b x=x.&.0xFF+b(x`shiftR`8)

Sayangnya saya harus menggunakan Network.Socketuntuk mendapatkan akses ke alamat IP jarak jauh sebagai bilangan bulat bukan string. Itu akan menyelamatkan puluhan karakter jika saya bisa melakukannya s <- listenOn (PortNumber n), daripada harus menelepon secara eksplisit socket, binddan secara listenindividual. Tapi, sayangnya, Network.acceptmemberi saya string host , bukan integer alamat IP , jadi saya harus menggunakan Network.Socket.acceptdan berteman.

Fungsi fmengambil nomor port sebagai argumen, dan membuat socket server ( s) mendengarkan pada port itu. Kemudian memanggil fungsi gdengan soket server. gloop selamanya, menerima koneksi. Fungsinyab mengambil alamat IPv4 aktual dan menghitung jumlah digitnya.

Saya yakin seseorang di suatu tempat dapat melakukan ini lebih baik daripada saya. Saya ingin memamerkan betapa mudahnya hal-hal soket di Haskell ... tapi kemudian gagal total, karena saya perlu akses ke alamat IP, yang biasanya tidak mudah didapat.


Paket "jaringan-sederhana" menyediakan antarmuka yang jauh lebih baik yang meneruskan SockAddr ke fungsi yang Anda berikan, yang membuat semuanya lebih mudah. Lihat solusi saya yang akan saya posting ...
Jules

Beberapa penyederhanaan jelas: (1) Saya percaya withSocketsDoini hanya diperlukan pada Windows, jadi jika berjalan di Linux itu dapat diabaikan; (2) 0xFF adalah karakter yang lebih panjang dari 255; (3) mengubah soket menjadi pegangan dan menggunakan IO biasa jauh lebih lama daripada menggunakan Network.Socket.send. Ya, sendsudah usang, tetapi alasannya tidak relevan dengan skenario ini (hanya terkait dengan teks atau data biner non-ASCII), jadi sepertinya masuk akal untuk menggunakannya.
Jules

Network.accept gives me a host string, not an IP address integerTidak bisakah Anda membagi string IP pada ".", mapfungsi string-to-number Haskell di atas string split dan menjumlahkan hasilnya?
kucing

2

Lua, 169 162 160 153 151 148 138 129 byte

Versi golf

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

Ini membutuhkan Luasocket untuk diinstal dan seorang juru bahasa yang mendukung label. Saya sudah mengujinya dengan Luajit dan saya juga dapat mengkonfirmasi bahwa kode tidak bekerja dengan Lua 5.1.

Versi tidak disatukan

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

Edit 1:

Diubah i=({c:getpeername()})[1]menjadi adili=c:getpeername()

Edit 2:

Kawat gigi dihapus dari pernyataan membutuhkan.

Edit 3:

Dihapus kawat gigi di sekitar vararg, mengurangi jumlah byte sedikit.

Edit 4:

Menghapus kurung sekitar "% d +", lebih pendek 2 byte.

Edit 5:

Menghapus variabel yang tidak perlu i.

Edit 6:

Mengubah ip dari "127.0.0.1" menjadi 0. (Terima kasih kepada xyzzy di #lua)

Edit 7:

Menghapus panggilan fungsi ke tonumber karena string dilemparkan ke angka secara otomatis (Terima kasih kepada Trebuchette atas sarannya, saya tidak tahu ini)


1
Hanya Lua 5.2 dan yang lebih tinggi yang mendukung label, jika Anda penasaran
Trebuchette

1
Selain itu, Lua secara otomatis melemparkan string ke angka dengan +operator, sehingga Anda dapat mengeluarkannya tonumber.
Trebuchette

2

Haskell, 185 (+ 19 = 204)? byte

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

Mengambil nomor port sebagai satu baris di stdin; membutuhkan network-simpledari Cabal.

Seperti biasa dengan jawaban Haskell yang tidak membatasi diri pada fungsi murni, the imports mengambil terlalu banyak byte. Newline tambahan juga bernilai 9 byte ...

Agak mirip dengan jawaban @ Jules, tapi saya menggunakan manipulasi string daripada operasi byte. Saya mencuri menggunakan -XOverloadedStringsekstensi juga, yang mungkin bernilai 19 byte tambahan.


2

C, 243 188 byte (atau mungkin 217 162 byte)

V2: lihat penjelasan di bawah ini.

188 byte:

s;main(g,v)char**v;{short S[8]={2,htons(atoi(v[1]))};char C[g=16];bind(s=socket(2,1,0),&S,g);for(listen(s,8);g=fdopen(accept(s,&C,&g),"w");fclose(g))fprintf(g,"%d\n",C[4]+C[5]+C[6]+C[7]);}

Sedikit berhati-hati 162 byte:

s;main(g){short S[8]={2,g};char C[g=16];bind(s=socket(2,1,0),&S,g);for(listen(s,8);g=fdopen(accept(s,&C,&g),"w");fclose(g))fprintf(g,"%d\n",C[4]+C[5]+C[6]+C[7]);}

Mungkin lebih banyak bermain golf besok pagi. Saya akan merapikan posting ini setelah pembaruan tersebut.


V1:

Yang ini sangat menyenangkan untuk bermain 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);}}

Ini berfungsi untuk IPv4. Sebagian besar ini merupakan implementasi langsung. Tiga komponen utama adalah

Membuat soket:

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

Kami menggunakan berbagai bentuk eksplisit dari konstanta AF_INET dll, dan memanfaatkan fakta bahwa ketika struct diinisialisasi dalam C dengan cara ini elemen yang tidak ditentukan ditetapkan ke nol.

Dengarkan klien, terima mereka, dan tutup koneksi mereka:

untuk (dengarkan (s, 8); c = terima (s, & C, & g); q = fclose (g))

Akhirnya untuk mengirim setiap klien data:

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

IP disimpan C.sin_addr.s_addrsebagai integer 32 bit di mana setiap oktet diwakili oleh salah satu dari empat byte. Kami menjumlahkan byte ini dengan for loop dan kemudian mencetaknya ke aliran menggunakan fprintf.

Saya memiliki solusi 217 byte yang lebih pendek tetapi saya tidak sepenuhnya yakin itu tidak melanggar celah standar karena mengharuskan port diberikan secara unary dalam urutan byte jaringan sebagai argumen baris perintah. Artinya, untuk menjalankan server pada port 12345 orang perlu menelepon

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

di mana jumlah total 1s adalah 14640. Untuk sedikitnya itu sedikit ... rumit. Tapi ini dia:

#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

Racket, 265 byte

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

Tidak Disatukan:

#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

Factor, 155 146 131 206 190 byte

Yah, saya baru belajar banyak tentang pemrograman soket tingkat rendah. Saya tidak berpikir saya pernah ingin melakukan itu lagi, karena saya thr kepala sakit.

[ 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 ya, utas, dan tidak kembali, benar.


Bisakah Anda menggunakan 10 base>bukan string>number?
fede s.

@ Feder. Wow, saya tidak pernah tahu itu ada. Saya pikir itu akan memungkinkan saya mempersingkat banyak jawaban Faktor saya!
kucing

Dan 10 >baseuntuk angka> string, juga.
fede s.

1
@ Feder. Mereka pantas mendapat jawaban di sini : D
cat
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.