Простой 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-Aliasnalпсевдонимом), чтобы сэкономить при повторном вводе 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/\./+/gy/./+/.
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.