Простой TCP-сервер


104

Напишите программу или функцию, которая прослушивает входящий TCP-трафик через порт N. Он предлагает простую услугу: он вычисляет сумму полей IP-адресов входящего соединения и возвращает.

Программа или функция читает целое число N из аргументов или стандартного ввода. Он прослушивает входящие TCP-соединения через порт N. Когда кто-то подключается к этому порту, программа вычисляет сумму полей своего IP-адреса и отправляет ее обратно клиенту с завершающим символом новой строки и закрывает соединение.

  • Номер порта N является допустимым, и 2 10 <N <2 15
  • Скользящие новая строка может быть \nили\r\n
  • Вы можете использовать IPv4 или IPv6. Поскольку адреса IPv6 записываются в шестнадцатеричной форме, вы также должны предоставить результат в том же формате, например 2001:0db8:0000:0042:0000:8a2e:0370:7334 => 12ecd.

Это . Применяются стандартные правила и лазейки.

пример

Вы запускаете свой сервер с ./server 1234. Теперь сервер работает и ожидает подключения через порт 1234. Затем клиент 127.0.0.1подключается к вашему серверу. Сервер выполняет простой расчет: 127+0+0+1 => 128и посылает результат к клиенту (с задней новой строки): 128\n. Затем сервер закрывает соединение и ждет следующего клиента.

Leaderboard

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
Разрешено ли использовать inetd / xinetd или аналогичный?
— Цифровая травма

91
Мне это нравится, так как это сложная игра в гольф, в которой языки гольфа вряд ли будут хороши.
— Исаак

9
Мало того, что удивительно, что TCP-сервер, по-видимому, очень простая в написании программа, я полностью поражен тем фактом, что он получает удовольствие от игры в гольф. Я просто вернусь к борьбе с FizzBuzz, как ненормальный.
— MonkeyZeus

17
@isaacg Это только время, когда кто-то находит встроенный TCP-сервер в Mathematica
— Downgoat

3
@MonkeyZeus Чтобы быть честным, вы не увидите здесь хорошего TCP-сервера. Сделать надежный, масштабируемый TCP-сервер, который хорошо обрабатывает все тонкости TCP (и вашего прикладного протокола), немного сложнее: D Хотя, безусловно, помогает, что протокол чрезвычайно прост - вам даже не нужно читать поток, что-то что я видел сломанный на слишком многих TCP серверах для подсчета: D
— Luaan

Ответы:


57

Bash + netcat + ss +…, 65 60 символов

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

Не серьезное решение, просто было любопытно об этой возможности.

Благодаря:

  • ninjalj за предложение awkфильтрации на основе (-5 символов)

Образец прогона:

(Терминал 1)

bash-4.3$ ./ip-reduce.sh 8080

(терминал 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.

В Ubuntu вы можете получить ncиз netcat-традиционных (нет, netcat-openbsd не очень хорошо) и ssиз iproute2 .


22
Почему вы говорите, что это не серьезное решение? Пока это работает, как ожидалось, я не вижу причин, почему это не должно считаться серьезным. Это также самый короткий с довольно значительным запасом на данный момент.
— Алекс А.

Наибольшее беспокойство по этому поводу возникло во время обсуждения с @JesseSielaff, когда я узнал, что в системах с настроенным IPv6 информация, связанная с сокетами, может быть отформатирована по-разному. Нет такой системы, чтобы проверить это. Для чего я думаю, будет ли правильнее превратить его в CW.
— manatwork

3
Насколько я понимаю, спецификация заключается в том, что вы должны поддерживать IPv4 или IPv6, а не оба. Так что, пока он работает для IPv4, поддержка IPv6 не должна иметь значения, я думаю.
— Алекс А.

1
@AlexA. По крайней мере, я думаю, что мой вопрос так говорит. Должен ли я уточнить это?
— Ханнес Карппила

@ HannesKarppila, твой вопрос ясен. Возможная проблема заключается в том, что мое решение может потребовать, чтобы операционная система была настроена определенным образом, чтобы иметь возможность работать. Поэтому я волнуюсь, потому что он может потерпеть неудачу, если настроен IPv6, независимо от того, обработаю я это или нет. Кто-то, у кого настроен IPv6, может сказать это наверняка ...
— manatwork

23

C #, 284 283 282 278 274 254 байта

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

Классический пример базового C # TCP-сервера. Тестирование:

Терминал 1:

$ ./Q76379.exe 1029

Терминал 2:

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

Fire Fox:


7
Вы можете сохранить 1 байт, используя int Mainвместо void Main. Поскольку программа никогда не возвращает, компилятор не требует returnутверждения.
— Разнагул

И нет, это не течь. Это на самом деле довольно детерминистично в отношении освобождения ресурсов. Кроме того, аргумент to Startявляется необязательным, сохраняя другой символ.
— Луаан

@Luaan Да, это осталось от отладки.
— LegionMammal978

Кроме того, вы можете использовать usingна TcpClient, который спасет вас еще три символа (используйте {}из от for), и делать то же самое с StreamWriterдолжен сохранить еще один.
— Луаан

@Luaan мне нужно явно , чтобы заставить ее работать должным образом. FlushStreamWriter
— LegionMammal978

22

Linux ELF / x86, 146 байт

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

Включает 52-байтовый заголовок ELF, 32-байтовый программный заголовок, 111 байтов программного кода + 3 байта кода для пропуска внутри заголовков.

Информация о том , как создавать крошечные ELF исполняемых файлов можно найти на сайте Breadbox «s „ вихре Учебник по созданию Really крохотный ELF Исполняемые для Linux “ .

Linux / i386 использует socketcall(2)мультиплексный системный вызов, который принимает ebxконкретный вызов сокета ( SYS_*макросы из /usr/include/linux/net.h) и ecxуказатель на область аргументов исходного вызова библиотеки.

Некоторые вещи сделаны, чтобы сохранить маленький исполняемый файл:

  • Предполагается, что регистры обнуляются при входе, что делает Linux, но это не требуется стандартом ELF (единственное требование заключается в том, что для EDXточек входа требуется функция финализации (полезно для исполняемых файлов, загружаемых динамическим компоновщиком) или значение NULL).
  • Предполагается, что при запуске (обычно с помощью оболочки) единственными открытыми файловыми дескрипторами являются 0, 1 и 2. Это означает, что прослушивающий сокет будет fd 3, а принятый сокет будет fd 4.
  • Предполагается, что есть ровно 2 аргумента (включая argv[0]).
  • То же место в стеке повторно используется для звонков bind(2), listen(2)и accept(2).
  • Для того, чтобы перескакивать через phentsizeи phnumполе, байты предваряются, превращается в CMPоперацию , которая принимает phentsizeи phnumполе , как непосредственные (трюк бесстыдно украдено из раствора Breadbox к 123 в анархии гольфах ).
  • Строковые операции x86 LODS(загрузка в аккумулятор и исходный индекс увеличения / уменьшения) и STOS(сохранение из аккумулятора и целевой индекс увеличения / уменьшения) хороши для короткого кода.
  • XCHG EAX, reg1 байт, по сравнению с MOV EAX, regкоторым занимает 2 байта.
  • CDQ/CLTD(знак расширения EAXв EDX:EAX) может использоваться как 1-байтовый способ обнуления EDXрегистра.
  • BSWAPполезно для реализации htons().

Источник носа:

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
Этот ответ недооценен.
— кот

16

NodeJS, 146 134 127 байт

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

Я наконец получил возможность опубликовать ответ NodeJS! IPv4 только сейчас.

Пример исполнения: node script.js 1024. Из другого терминала:

$ curl 127.0.0.1:1024
128

2
Я считаю 127 байтов прямо сейчас, хотя вы можете уменьшить его до 126, поменяв местами '\n'шаблонную строку, содержащую буквальный перевод строки.
— Mwr247

Разве это не противоречит требованиям, потому что вы создаете HTTP-сервер, я имею в виду, что это технически TCP-сервер, но не могли бы вы просто использовать модуль TCP и сохранить себя как персонажа?
— MayorMonty

14

Tcl, 92

  • 1 байт сохранен благодаря @DonalFellows.
proc s {c a p} {puts $c [expr [string map .\ + $a]]
close $c}
socket -server s $argv
vwait f

Довольно понятно,

socket -server s $argv создает прослушивающий сокет на порту, указанном в аргументах.

Каждый раз, когда приходит новое соединение, proc sвызывается, с каналом, адресом источника и портом источника в качестве параметров. string mapзаменяет .для +в адрес источника, и exprарифметически оценивает результат, который затем putsобратно к каналу связи c.

vwait запускает цикл обработки событий для перехвата входящих событий подключения.


Благодарим @DonalFellows за следующее:

Вот версия, которая обрабатывает IPv6 (требуется Tcl 8.6; большая часть дополнительной длины связана с получением шестнадцатеричного ответа):

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
Использование apply, похоже, ничего не спасает. И вы не можете использовать, так tcl::mathop::+ {*}[split $a .]как это немного дольше. Вы также не можете побрить что-либо из названий опций. Но добавить поддержку IPv6 довольно просто, и стоит всего лишь несколько байтов кода (и тогда regsubподход на основе такой же длины).
— Донал Феллоуз

аааа, Tcl / Tcl-DP ... потрясающая куча инструментов. (в 90-х годах профессор показал нам, что мы можем написать распределенный по сети Excel (с сеткой, включая оценку формул!), который будет разделен между несколькими людьми с (iirc) 4 (короткими) строками для сервера и 5 для клиентов. ..
— Оливье Дюлак

proc s {c a p}тебе действительно нужны все эти пробелы?
— кот

12

Groovy 133 , 125 , 93 , 89

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

Только IPv4, наверное.

Ungolfed:

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

Тестирование:

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

1
.toInteger()→ as intи s.inetAddress.address*.toInteger()→ (s.inetAddress.address as int[]). И есть дополнительное место после .with.
— Манатворк

@ Manatwork THX! Обновлено.
— Будет ли Lp

9

Python 3, 170 166 147 байт

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

Принимает порт stdin, только IPv4. Работает в GNU / Linux (и, как я полагаю, в большинстве других версий), который автоматически расширяет "" до "0.0.0.0", хотя не уверен насчет Windows.


2
Вы можете сохранить несколько байтов. Во-первых, пробелы в import *и , SOCK_STREAMне нужны. Кроме того, строка отправки может быть записана более эффективно, как c.send(b"%d\n"%eval(a[0].replace(".","+"))).
— Ханнес Карппила

2
@ HannesKarppila о, спасибо. забыл про места, eval hack довольно круто, хотя.
— Саммко

2
AF_INET и SOCK_STREAM - это просто константы; AF_INET равен 2, а SOCK_STREAM равен 1. Также, как уже упоминалось, SOCK_STREAM не требуется; так что вы можете сократить это, используя вместо этого s=socket(2).
— Скайлер

1
Вы не можете просто сделать socket () и, следовательно, сохранить еще один байт?
— Foon

1
Вы можете сохранить 10 символов с помощью Python 2. Затем int(input())становится input()и отправляется частьc.send(`eval(a[0].replace(".","+"))`)
— Blender

9

Java, 371 368 350 344 333 310 295 282 байта

Golfed

import java.net.*;class A{public static void main(String[]n)throws Exception{ServerSocket s=new ServerSocket(Integer.decode(n[0]));for(;;){try(Socket a=s.accept()){byte[]c=a.getInetAddress().getAddress();new java.io.PrintStream(a.getOutputStream()).println(c[0]+c[1]+c[2]+c[3]);}}}}

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

Выход

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

1
Удалите int k=и замените k со всеми вещами в Integer.toString(k). Чтобы сэкономить несколько байтов.
— GiantTree

1
Байт Javas почти наверняка испортит возвращаемое значение для 192.168.2.1 или аналогичных адресов с байтом выше 127.
— AlexR

1
Изменения interfaceв classдолжны получить еще несколько байт
— Ортис

2
Используйте a.getOutputStream().write((c[0] + c[1] + c[2] + c[3]+"\n").getBytes());вместоnew DataOutputStream(a.getOutputStream()).writeBytes(c[0] + c[1] + c[2] + c[3] + "\n")
— Ortis

3
Не try(Socket a=...){}короче чем a.close();? Требуется Java 7, но может получать байты.
— Оливье Грегуар

8

PowerShell v2 +, 303 268 257 227 байт

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 байтов благодаря Мэтту ... Еще 11 байтов сохранили с помощью псевдонимов New-Objectи незначительных изменений ... Еще 30 байтов неявно использовали localhost, а не anyIP-адрес, и исправили, чтобы учесть непрерывное использование, как было указано изначально, и я пропустил

Действительно похоже на ответ C # , поскольку это .NET лежит в основе обоих. Мы сохраняем несколько байтов здесь по сравнению с ответом на C #, используя возможность возврата функциональности PowerShell (окружая нашу декларацию / присваивание в скобках, а затем немедленно вызывая методы.), Но мы теряем очень много из-за необходимости формулировать суммирование , Тот факт, что у нас есть несколько более короткие имена классов / вызовов, действительно объясняет, почему этот ответ превосходит C #.

объяснение

Сначала мы создаем New-Alias(с nalпсевдонимом), чтобы сэкономить при повторном вводе New-Objectпозже. В остальной части первой строки настраивается прослушиватель TCP. Мы передаем командную строку $args[0]как вход для создания нового System.Net.Sockets.TcpListener, сохраняемого как $l. Этот объект инкапсулируется в parens и немедленно вызывается, .Start()чтобы он активно открыл сокет.

Войдя в бесконечный forцикл, мы затем устанавливаем наш слушатель $lна блокировку, с AcceptTcpClient()которой будет ждать соединения. Ссылка на это соединение (после того, как оно установлено) сохраняется в $cинкапсулированном виде в скобках и немедленно вызывается GetStream()для получения потока данных. Этот поток данных передается новому System.IO.StreamWriterконструктору $w, поэтому мы можем им манипулировать. Этот конструктор сам заключен в скобки и сразу вызывается Write(...).

Внутри Write(...)вызова мы берем наш дескриптор клиента $cи получаем его RemoteEndPointсобственность. Это единственный способ (который я нашел) получить удаленный IP-адрес. Затем нам нужно повторно привести его как [System.Net.IPEndPoint]объект, чтобы он правильно отформатирован, инкапсулировать это в скобках и извлечь только .Addressсвойство. Затем мы -replaceзаписываем буквальные периоды со знаком плюс, а затем направляем его Invoke-Expression(аналогично eval) для получения нашего суммирования.

После записи ввода / вывода нам нужно позвонить, .Dispose()чтобы убедиться, что поток данных сброшен на клиент и закрыт. TCP-сервер прерывает соединение с клиентом без предупреждения, поэтому в зависимости от используемого клиента он может зависнуть на некоторое время. Затем он продолжает forцикл без надлежащего закрытия соединений. Это также означает, что он теряет память и системные дескрипторы как сумасшедшие, но нас это не волнует, верно? Тем не менее, вам может понадобиться использовать диспетчер задач, чтобы завершить процесс, когда вы закончите работу сервера. : D

Кроме того, только IPv4, так как суммирование barfs впечатляюще пытается обработать IPv6-адрес, поскольку :не является допустимым алгебраическим оператором для iexанализа.


2
«Утечки памяти и системных ручек как сумасшедшие» Что, ты free()им после? delete[], может быть? : P
— кошка

8
@tac Да, есть целый ряд методов .close()и .dispose()методов, которые мы здесь не называем, которые могли бы привести людей в Code Review в порядок.
— AdmBorkBork

О, разве PS GC'd? Или GC выполняет пересчет, а не анализ объема?
— кот

@tac Да, PowerShell действительно выполняет сборку мусора благодаря базовой системе .NET. Но, в зависимости от того, как вы вызываете или используете этот скрипт, вы можете столкнуться с ошибками, такими как эта утечка памяти в конвейере. Вышеприведенный код также не является поточно-ориентированным, и поэтому может столкнуться с проблемами GC, поскольку мы не закрываем сокет явно.
— AdmBorkBork

1
В тестировании я не мог заставить это работать, вероятно, из-за проблем с брандмауэром, которые я не чувствую как исправить, поэтому я не могу быть уверен, но ..... Я думаю, что вы можете отбросить "Систему" из большинства, если не из всех типов. у вас там т.е. [Net.ipaddress]::Anyработает.
— Мэтт

7

PHP, 161 (56?)

Это мой первый пост здесь. Я надеюсь, что это идет правильно :)

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

Терминал:

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

Это работает только для IPV4

Редактировать : я только что заметил, что php поддерживает базовый сервер:
я решил придерживаться первоначального количества символов, если кто-то не подтвердит, разрешено ли следующее :)

test2.php: (возможно 56-байтовое решение)

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

И затем начните обслуживание с:

php -S localhost:8080 test2.php

Chrome как клиент Скриншот

Редактировать 2: wget как клиент

$ wget -qO- localhost:8080
128

Я знаю, правила говорят: «Программа или функция читает целое число N из аргументов или стандартного ввода», но это нормально, если программа в этом случае является сам PHP? Или использование встроенного сервера в PHP считается лазейкой?
— Микаэль

Добро пожаловать в Программирование Пазлов и Code Golf! Ваше 161-байтовое решение выглядит великолепно. 56-байтовое решение, под которым вы упомянули, - то, под которым test2.php? Если это так, я думаю, вам нужно будет спросить у ОП, считают ли они, что встроенные устройства приемлемы для этой задачи. Это не лазейка, хотя.
— Алекс А.

Я бы сказал, что использование встроенного TCP-сервера было бы приемлемо, но в этом случае мы говорим о встроенном HTTP-сервере . Таким образом, 56-байтовое решение 1) ничего не делает, если клиент только соединяется и ничего не отправляет; 2) отправляет обратно только «[Wed Mar 30 10:15:02 2016] 127.0.0.1:47974 Invalid request (Malformed HTTP request)» без запуска test2.php в случае, если клиент отправляет, например, «foo»; 3) отправляет полный набор заголовков ответа HTTP до фактического требуемого ответа в случае, если клиент отправляет действительный запрос HTTP.
— Манатворк

@Alex A. Спасибо и да, 56-байтовое решение находится под test2.php :)
— Микаэль

@manatwork Вы правы, но я думал, что клиент не определен в этом задании. Так можно ли использовать браузер или, что еще проще, что-то вроде "wget ​​-qO- localhost: 8080" в качестве клиента?
— Микаэль

7

Go , 359 311

Это моя первая программа на Go - она ​​позволила мне понять одну вещь: это определенно не очень хороший язык для игры в гольф!

(Престижность @steve, который сделал большую часть игры в гольф!)

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
Но это конечно хороший язык для создания tcp сервера!
— Нумери

1
Странно, я получаю результат 360 при подключении с 192.168.0.67, а не с 427.
— Стив

3
Вы можете назвать пакеты strings + strconv, чтобы сэкономить несколько байтов. например, "strings"становится s "strings"так, что позднее strings.Splitстановится справедливым s.Split.
— Стив

1
Еще несколько байт сбрил pastebin.com/HY84sazE - начинает выглядеть немного больше «golfed» Сейчас
— Стиву

2
Если вы используете import(."pkgname")все функции, которые будут импортированы в текущее пространство имен, вы можете удалить префикс. например. import ."fmt"; Println("foo") Если вы используете пакет Sscanfиз fmtпакета для анализа адреса вместо регулярных выражений, это сэкономит вам еще несколько байтов, предоставив вам приятный бонус Fprintlnза возврат суммы вместо импорта strconv.
— Кристоффер Салл-Сторгард

7

Common Lisp, 110 байт

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

подробности

(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 для Common Lithp!
— кот

6

q, 88 байтов

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: Принимает второй аргумент командной строки (первый "-"для запрета qинтерпретировать Nкак скрипт / файл) и открывает с ним порт ( "p ").
    • Примечание. При вызове q -p Nпорт устанавливается Nавтоматически, но, поскольку вопрос, по-видимому, предполагает, что это Nдолжен быть аргумент программы, а не сам исполняемый файл, я пошел более длинным путем.
  • Внутри .z.pgфункции, которая обрабатывает входящие запросы, .z.aIP-адрес хранится в виде 32-разрядного целого числа.
    • "i"$0x0 vsразбивает его на целочисленные «составляющие» и sumвыполняет суммирование.
    • Наконец, stringчисловой результат и добавление "\n"к нему для возврата клиенту.
  • .z.ph это еще одна функция для запросов HTTP GET, с дополнительной обработкой для преобразования вывода строки в действительный ответ HTTP.

Демо-сервер:

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)

Демо-клиент (из другого qзапущенного сеанса 127.0.0.1):

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

Демо - Клиент (с curl):

$ curl localhost:1234
128

$

6

LiveScript, 107 105 байт

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

Больше нечего добавить, это просто базовые вещи NodeJS. Точки стиля для &1(второй аргумент), <|(трубопровод F #, похожий на $Haskell) и biop: (+)в LS подобны секциям операторов в Haskell: бинарная карри-функция (которая добавляет свои операнды). Также немного грязно: /если задана литеральная строка справа, будет делиться.


5

Perl, 141 132 + 1 = 133 байта

Golfed

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

пример

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

Вы уверены, что это правильно? Я получаю сумму, напечатанную на терминале сервера, а не на клиенте. В любом случае, вы можете удалить все скобки и изменить s/\./+/g→ y/./+/.
— manatwork

Ааа, неправильно прочитал ... Буду соответственно пересматривать и включать ваше хорошее у / предложение.
— Стив

1
while(1){…}→ {…;redo}согласно user130144 большой «ы наконечник . И, кроме ->send()вызова, все остальные скобки не нужны.
— Манатворк

4

Python 2, 180 байт

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

Принимает порт через стандартный ввод.


4

NodeJS (ES6), 129 118 107 байтов

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

Работает на IPv4. Беги какnode server.js <port>


На самом деле не работает, если сервер использует IPv6 (как, например, мой делает автоматически), так c.remoteAddressкак тогда будет ::ffff:127.0.0.1. (Я тестировал на Node v5.9.1).
— Frxstrem

Кроме того, у вас нет завершающего символа новой строки, который должен увеличить ваш счет на 2 байта.
— Frxstrem

@Frxstrem Ой, забыл эту новую строку. Добавляет только 1 байт, хотя благодаря шаблонным строкам. Относительно семейства IP: .listen()сначала используется по умолчанию IPv4, но похоже, что по ошибке или по дизайну это изменилось. Отправка будет по-прежнему функционировать должным образом в более новых версиях узла, когда IPv6 отключен на хост-компьютере.
— Mwr247

4

Go, 211 байт

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

Возможно, дальше можно играть в гольф, я не совсем удовлетворен тем, как мне, например, приходится разбирать IP-адрес, это выглядит как ужасный взлом.

Прослушивает IPv4 на порту, указанном в качестве аргумента.


4

PowerShell, 208 206 192 152 байта

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

информация о версии:

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

Спасибо TimmyD за то, что сэкономили мне 14 байтов!

Огромное спасибо TessellatingHeckler за спасение мне 40 байт


@TimmyD ах, упс, я пропустил, что это было необходимо ... исправлено сейчас
— Nacht

Один из способов, которым программы могут принимать входные данные - от stdin. Я полагаю, что этот конкретный вопрос не указывает, что это разрешено, но это общая вещь, касающаяся игры в гольф, которая, я думаю, должна учитываться для PowerShell. К сожалению, он отличается от bash тем, что не ожидает ввода на stdin, если ничего не было предоставлено.
— яхта

справедливо. снова исправлено
— Nacht

Хорошо, теперь для некоторых гольфов - попробуйте следующее в 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
Я думаю, что вы можете свалить это до 152 - отбросить новый объект и выполнить приведение напрямую, пропустить преобразование байтового массива и выполнить приведение строки по-другому, вообще не хранить $ x и удалить оставшиеся параметры для send (), и это становится ($t=[net.sockets.tcplistener]$args[0]).start();for(){($z=$t.acceptsocket()).send([char[]]"$($z.remoteendpoint.address-replace"\.","+"|iex)");$z.close()}- что я только быстро протестировал с подключением netcat, но, похоже, работает так же - подключение с localhost в любом случае.
— TessellatingHeckler

4

Машинный код 8086 (16-битный DOS), 163 156 148 148 142 байта

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

Эквивалентный код сборки:

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

Это предполагает, ntcpdrvчто загружен в INT 0x61(и любой подходящий драйвер пакета в 0x60). Компилировать с fasm tcpserv.asm.

У него есть некоторые проблемы:

  • Он не проверяет, является ли аргумент действительным номером порта, или это вообще число.
  • Клиент должен отправить хотя бы один байт, поскольку я не могу найти другого способа узнать, подключился ли клиент.
  • Работает только один раз и зависает со второй попытки. Работает снова после перезагрузки.
  • Возвращаемое значение дополняется нулями слева.
  • Это моя самая первая запись в гольф кода, а также моя самая первая программа 8086 asm. Я уверен, что есть способы улучшить это дальше.

1
Вы можете просто опубликовать hexdump скомпилированного вывода для 148 байтов
— cat

Это разрешено? Это сделало бы эту запись немного более конкурентоспособной ...
— user5434231

1
Хорошо, я изменил запись на машинный код. Также сбрил еще несколько байтов, используя xor r,rвместо mov r,0.
— user5434231

1
Я написал это на дос-машине, где есть новые строки CR LF, поэтому я просто пошел с этим. В любом случае посчитать размер ассемблера сейчас бессмысленно, с тем же успехом можно немного его очистить и добавить несколько комментариев.
— user5434231

1
Это должно произойти и здесь, и это работает; int 0x61возвращает случайный локальный порт в ax. Но это также изменяет прослушивающий IP на какой-то мусорный номер ( 4.2.0.0iirc)
— user5434231,

3

Haskell, 216 байт

Использование пакета "network-simple" ( cabal install network-simple). Требуется пара языковых расширений ( -XOverloadedStrings -XNoMonomorphismRestriction) для работы.

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)

Есть несколько возможных упрощений, включая изменение wфункции для непосредственного возврата суммы, а не списка, и использование функции, а не программы, чтобы в качестве аргумента можно было указать номер порта. Я не думаю, что это сильно уменьшит размер. 20 байтов что ли?


Приятно! Уверен , вы все еще можете бриться несколько байт от переименованием wк #, так w h nстановится h#nдля экономии в 2 байта на использование.
— Actorclavilis

3

Свинка 114 115 байт

Golfed:

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

Это версия Mumps InterSystems Caché - если есть версия, которая может получить адрес TCP короче ##class(%SYSTEM.TCPDevice).PeerAddr() (так как это почти 1/3 всей программы), у нее может быть больше шансов против некоторых других опубликованных языков. ... ;-)

Редактировать: Благодаря @TimmyD - я пропустил чтение порта из STDIN или аргументов вместо того, чтобы быть жестко закодированным. Под редакцией; это добавило 1 байт к программе.


@TimmyD - Ах, ты прав. Пропустил это при прочтении требований. Буду редактировать постхаст.
— 1

3

C 535 байтов

Ну, кто-то должен был сделать это.

Я добавил один разрыв строки, чтобы опубликованный код на самом деле содержал 536 символов.

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

компилировать с gcc [file_name] -o server

бежать с ./server [port]

соединить с telnet localhost [port]


3
Хороший ответ! Как упоминалось ранее , вы можете сохранить несколько байтов, используя фактические значения для некоторых констант, таких как AF_INET и SOCK_STREAM.
— Ханнес Карппила

2

Java, 210 байт

Golfed:

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

Expanded:

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

Это собрание всех советов, которые я дал в других ответах на Java, плюс написание в виде функции вместо полной программы, которая получает примерно 70 байт по сравнению с программой.


2

Haskell, 326 байт

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)

К сожалению, мне пришлось использовать, Network.Socketчтобы получить доступ к удаленному IP-адресу в виде целого числа, а не строки. Это спасло бы десятки персонажей , если я мог бы просто сделать s <- listenOn (PortNumber n), вместо того , чтобы явно вызывать socket, bindи в listenиндивидуальном порядке . Но, к сожалению, Network.acceptвыдает мне строку хоста , а не целое число IP-адресов , поэтому мне пришлось прибегнуть Network.Socket.acceptи к друзьям.

Функция fпринимает номер порта в качестве аргумента и создает сокет сервера ( s), прослушивающий этот порт. Затем он вызывает функцию gс сокетом сервера. gпетли навсегда, принимая соединения. Функция bберет фактический адрес IPv4 и вычисляет сумму его цифр.

Я уверен, что кто-то может сделать это лучше меня. Я хотел показать, насколько чертовски просты сокеты в Haskell ... но потом с треском провалился, потому что мне нужен доступ к IP-адресу, который обычно нелегко получить.


Пакет "network-simple" предоставляет гораздо более приятный интерфейс, который передает SockAddr функции, которую вы ему предоставляете, что упрощает работу. Смотрите мое решение, которое я собираюсь опубликовать ...
— Жюль

Очевидны некоторые упрощения: (1) я считаю, что withSocketsDoэто необходимо только в Windows, поэтому при работе в Linux это можно игнорировать; (2) 0xFF - символ длиннее 255; (3) преобразование сокета в дескриптор и использование обычного ввода-вывода намного дольше, чем использование Network.Socket.send. Да, sendне рекомендуется, но причина не имеет отношения к этому сценарию (это относится только к тексту или двоичным данным, не относящимся к ASCII), поэтому представляется разумным использовать его.
— Жюль

Network.accept gives me a host string, not an IP address integerРазве вы не можете просто разделить строку IP на ".", mapфункции в Haskell строка-к-номеру над разделенной строки и подвести итоги?
— кот

2

Lua, 169 162 160 153 151 148 138 129 байт

Гольф версия

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

Для этого требуется установить Luasocket и интерпретатор, поддерживающий метки. Я протестировал его с Luajit, и я также могу подтвердить, что код не работает с Lua 5.1.

Неуправляемая версия

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

Изменить 1:

Изменено i=({c:getpeername()})[1]на простоi=c:getpeername()

Изменить 2:

Удалены фигурные скобки из оператора require.

Изменить 3:

Убраны скобки вокруг vararg, немного уменьшено количество байтов.

Изменить 4:

Убрана скобка вокруг "% d +", короче на 2 байта.

Изменить 5:

Убрал ненужную переменную i.

Изменить 6:

Изменен ip с "127.0.0.1" на 0. (Спасибо xyzzy на #lua)

Изменить 7:

Удален вызов функции для tonumber, поскольку строки автоматически приводятся к числам (спасибо Trebuchette за предложение, я этого не знал)


1
Только Lua 5.2 и выше поддерживающие ярлыки, если вам интересно
— Trebuchette

1
Кроме того, Lua автоматически переводит строки в числа с +оператором, так что вы можете вынуть tonumber.
— Требушетт

2

Хаскелл, 185 (+ 19 = 204)? байтов

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)

Принимает номер порта как одну строку на стандартном вводе; требует network-simpleот Кабала.

Как обычно с ответами на Haskell, которые не ограничиваются чисто функциями, они importsзанимают слишком много байтов. Конечный перевод строки также стоит 9 байт ...

Несколько похоже на ответ @ Jules, но я использую манипуляции со строками вместо байтовых операций. Я воровал использовал -XOverloadedStringsрасширение , а также, что, вероятно , стоит 19 байт дополнительно.


2

C 243 188 байт (или, возможно, 217 162 байт)

V2: см. Ниже для объяснения.

188 байт:

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 байта:

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

Возможно, завтра утром возможно еще больше игры в гольф. Я приведу этот пост в порядок после этих обновлений.


V1:

Этот был действительно довольно забавен для гольфа.

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

Это работает для IPv4. В основном это простая реализация. Три основных компонента

Создание сокета:

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

Мы используем различные явные формы констант AF_INET и т. Д., И используем тот факт, что когда структура инициализируется в C таким способом, неуказанные элементы устанавливаются в ноль.

Слушайте клиентов, принимайте их и закрывайте их соединения:

для (прослушивания (с, 8); с = принять (с, & C, & г); д = fclose (г))

Наконец, чтобы отправить каждому клиенту данные:

для (г = 4; г; д + = C.sin_addr.s_addr >> 8 * - г & 255); fprintf (г = fdopen (с, "ш"), "% d \ п", д);

IP хранится в C.sin_addr.s_addrвиде 32-разрядного целого числа, где каждый октет представлен одним из четырех байтов. Мы суммируем эти байты с циклом for и затем печатаем их в поток, используя fprintf.

У меня есть более короткое 217-байтовое решение, но я не совсем уверен, что оно не нарушает стандартные лазейки, поскольку требует, чтобы порт был задан в одинарном порядке в байтах сети в качестве аргументов командной строки. То есть для запуска сервера через порт 12345 нужно было бы позвонить

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

где общее число 1s составляет 14640. По меньшей мере, это немного ... громоздко. Но вот это все равно:

#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

Ракетка, 265 байтов

#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

Фактор 155 146 131 206 190 байт

Ну, я только что многое узнал о низкоуровневом программировании сокетов. Я не думаю , что когда - нибудь хочу сделать это снова, потому что мой Чет болит голова.

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

Ах да, с резьбой, и не возвращается, верно.


Вы можете использовать 10 base>вместо string>number?
— Федерация с.

@fedes. Вау, я никогда не знал, что существует. Я думаю, что это позволит мне сократить многие из моих факторных ответов!
— кот

И 10 >baseдля числа> строка тоже.
— Федерация с.

1
@fedes. Те заслуживают ответа здесь : D
— кот
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.