echoクライアント
Posted feedbacks - Flatten
Nested Hiddenこんな感じでしょうか。
1 2 3 4 5 6 7 8 9 | echo.client <- function(host.name="localhost", port.number=9999){
sock <- socketConnection(host=host.name, port=port.number)
repeat{
writeLines(readLines(), sock)
writeLines(readLines(sock, n=1))
}
}
argv <- commandArgs(trailingOnly=T)
echo.client(argv[1], argv[2])
|
1 2 3 4 5 6 7 8 9 10 11 | require 'socket'
host = ARGV[0]
port = ARGV[1].to_i
TCPSocket.open(host, port) { |s|
while $stdin.gets
s.write $_
print s.gets
end
}
|
IO::* モジュールを使って。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | use strict;
use warnings;
use IO::Socket::INET;
use IO::Handle;
my $s = IO::Socket::INET->new(
PeerAddr => $ARGV[0],
PeerPort => $ARGV[1],
) or die "failed to open $ARGV[0]:$ARGV[1]";
my $i = IO::Handle->new_from_fd(*STDIN, q/r/);
my $o = IO::Handle->new_from_fd(*STDOUT, q/w/);
my $buf;
while ( my $bytes = $i->read($buf, 256) ) {
$s->syswrite($buf);
$s->read($buf,$bytes);
$o->syswrite($buf);
}
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | using System;
using System.IO;
using System.Net.Sockets;
class P
{
static void Main(string[] args)
{
TcpClient c = new TcpClient(args[0], int.Parse(args[1]));
NetworkStream s = c.GetStream();
TextWriter w = new StreamWriter(s);
TextReader r = new StreamReader(s);
string l = null;
while ((l = Console.ReadLine()) != null)
{
w.WriteLine(l);
w.Flush();
Console.WriteLine(r.ReadLine());
}
}
}
|
Squeak Smalltalk で。
1 2 3 4 5 6 7 8 9 10 | | serverAddress portNumber socket string |
serverAddress := NetNameResolver addressFromString: '127.0.0.1'.
portNumber := 9999.
socket := Socket newTCP.
socket connectTo: serverAddress port: portNumber.
World findATranscript: nil.
[(string := FillInTheBlank request: 'string:') notEmpty] whileTrue: [
socket sendData: string, String crlf.
Transcript show: socket receiveData].
socket close
|
$ python client_echo.py localhost 7 < input_file > result_file
1 2 3 4 5 6 7 8 9 10 11 12 13 | #!/usr/bin/python
# -*- coding: utf8 -*-
import sys, socket
host, port = sys.argv[1:3]
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((host, int(port)))
sf = s.makefile()
for line in sys.stdin:
sf.write(line)
sf.flush()
print sf.readline(),
|
PHP 5.1.6
$ php -q client_echo.php localhost 7 < input_file > result_file
1 2 3 4 5 6 7 8 9 10 11 12 13 | #!/usr/bin/env php
<?php
$host = $argv[1];
$port = $argv[2];
$sock = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
socket_connect($sock, $host, $port);
while ($line = fgets(STDIN, 1024)) {
socket_write($sock, $line, strlen($line));
echo socket_read($sock, 1024);
}
?>
|
クライアント機能に限定したnetcatコマンドを作りなさい、ということかしら?
1 2 3 4 5 6 7 8 9 10 11 | (use gauche.net)
(use util.stream)
(call-with-client-socket
(make-client-socket 'inet (car *argv*) (x->integer (cadr *argv*)))
(lambda (i o)
(stream-for-each
(lambda (l)
(display #`",|l|\n" o)
(print (read-line i)))
(port->stream (current-input-port) read-line))))
|
ocamlfind c -package unix -linkpkg -o echoc echoc.ml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | open Unix
let conn host port =
let hostent = gethostbyname host in
open_connection (ADDR_INET(hostent.h_addr_list.(0), port))
let main () =
let (ich, och) = conn Sys.argv.(1) (int_of_string Sys.argv.(2)) in
let rec loop () =
let str = read_line () in
Printf.fprintf och "%s\r\n" str; flush och;
print_endline (input_line ich);
loop () in
loop ()
let _ = main ()
|
題意が分かりにくかったのでしょうか。申し訳ありません。
自分が想定していたのは、Pythonで書くなら以下のようなコードだったのですが、題意はご自由に解釈していただいて構いません。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | #!/usr/bin/env python
import sys
import os
import socket
from threading import Thread
class Receiver(Thread):
def __init__(self, sock):
Thread.__init__(self)
self.src = sock
def run(self):
for data in iter(lambda: self.src.recv(8192), ""):
os.write(sys.stdout.fileno(), data)
def main(args):
if len(args) < 3:
print >>sys.stderr, "usage: %s host port" % args[0]
sys.exit(1)
if sys.platform == 'win32':
sys.stdin.setmode(os.O_BINARY)
sys.stdout.setmode(os.O_BINARY)
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect((args[1], int(args[2])))
receiver = Receiver(sock)
receiver.start()
for data in iter(lambda: os.read(sys.stdin.fileno(), 8192), ""):
sock.send(data)
sock.shutdown(socket.SHUT_WR)
receiver.join()
sock.close()
return 0
if __name__ == '__main__':
main(sys.argv)
|
ええと、さっきのは#7138さんへのレスです。それと、コードが間違っていたので修正します。 setmode()はmsvcrtの関数でした。
「netcatのクライアント部分と同等」であるかは、netcatコマンドの仕様に詳しくないので、申し訳ありませんが何ともいえません。
echoはR.Stevensのunpvのようなネットワークプログラミングの教科書の最初のサンプルとして出てくることが多いでしょうから、その多言語版クックブックという観点を考えていました。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | #!/usr/bin/env python
import sys
import os
import socket
from threading import Thread
import msvcrt
class Receiver(Thread):
def __init__(self, sock):
Thread.__init__(self)
self.src = sock
def run(self):
for data in iter(lambda: self.src.recv(8192), ""):
os.write(sys.stdout.fileno(), data)
def main(args):
if len(args) < 3:
print >>sys.stderr, "usage: %s host port" % args[0]
sys.exit(1)
if sys.platform == 'win32':
msvcrt.setmode(sys.stdin.fileno(), os.O_BINARY)
msvcrt.setmode(sys.stdout.fileno(), os.O_BINARY)
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect((args[1], int(args[2])))
receiver = Receiver(sock)
receiver.start()
for data in iter(lambda: os.read(sys.stdin.fileno(), 8192), ""):
sock.send(data)
sock.shutdown(socket.SHUT_WR)
receiver.join()
sock.close()
return 0
if __name__ == '__main__':
main(sys.argv)
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | module Main where
import Control.Arrow
import Control.Exception (bracket)
import System.Environment (getArgs)
import Network (connectTo, PortID(..))
import System.IO
func :: Kleisli IO (Handle,String) ()
func = arr ((first hPutStr >>> app)
&&& ((hGetLines *** length . lines) >>> app))
>>> Kleisli join'
>>> Kleisli (snd >>> mapM_ putStrLn)
where join' :: (Monad m) => (m a,m b) -> m (a,b)
join' (mx,my) = mx >>= \x -> my >>= \y -> return (x,y)
hGetLines handle n
| n == 0 = return []
| otherwise = hGetLine handle
>>= \l -> hGetLines handle (pred n)
>>= return . (:) l
echo :: String -> Handle -> IO ()
echo s handle = do
hSetBuffering handle LineBuffering
runKleisli func (handle,s)
main = do
(h:p:_) <- getArgs
s <- getContents
bracket (connectTo h (port p)) hClose (echo s)
where port = PortNumber . fromIntegral . read
|
Javaがまだの様なので。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 | import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
class Echo {
Socket socket;
OutputStream out;
InputStream in;
public Echo(String host,int port) throws Exception {
socket = new Socket(host,port);
out = socket.getOutputStream();
in = socket.getInputStream();
}
public void echo(int size,byte[] request) throws Exception {
byte[] response= new byte[size];
out.write(request,0,size);
out.flush();
in.read(response,0,size);
System.out.write(response,0,size);
}
public void close() throws Exception {
socket.close();
}
public static void main(String[] args) {
try {
Echo echo = new Echo(args[0],Integer.parseInt(args[1]));
byte[] request = new byte[2048];
int size;
while ((size = System.in.read(request)) > 0) {
echo.echo(size,request);
}
echo.close();
} catch(Exception ex) {
ex.printStackTrace();
}
}
}
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | try {
host = args[0]
port = args[1].toInteger()
} catch (e) {
println "usage: groovy ${this.class.name} host port"
System.exit 1
}
new Socket(host, port).withStreams { is, os ->
dis = new DataInputStream(is)
buf = new byte[1024]
while ((len = System.in.read(buf)) >= 0) {
os.write(buf, 0, len)
dis.readFully(buf, 0, len)
System.out.write(buf, 0, len)
}
}
|
echoのプロトコル(RFC862)に詳しくないのですが、サーバ側からデータの終わり(eofなど)が返ってこないようなので、タイムアウト(10秒)を設定してみました(汗
送信したデータと比較して、同じならcloseする条件もつけました。
escriptが利用可能な環境であれば、以下のようにコマンドラインから実行可能です。
$ ./スクリプト名 localhost 7 < testfile > newfile
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | #!/usr/bin/env escript
main([Hostname, Port])->
Str = loop(io:get_line(standard_io,''), []),
Res = gen_tcp:connect(Hostname,
list_to_integer(Port),
[binary, {packet, 0}]),
case Res of
{ok, Socket} ->
ok = gen_tcp:send(Socket, Str),
receive_data(Socket, [], lists:flatten(Str));
{error, Why} -> io:format("error ~p~n", [Why]), exit(eError)
end.
receive_data(Socket, _Original, _Original) ->
gen_tcp:close(Socket);
receive_data(Socket, SoFar, Original) ->
receive
{tcp, Socket, Bin} ->
Lines = binary_to_list(Bin),
io:format("~s", [Lines]),
receive_data(Socket, lists:flatten(SoFar ++ [Lines]), Original);
{tcp_closed, Socket} ->
ok
after 10000 ->
gen_tcp:close(Socket)
end.
loop(eof, SoFar)->
lists:reverse(SoFar);
loop(Data, SoFar) ->
loop(io:get_line(''), [Data|SoFar]).
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | #include <iostream>
#include <string>
#include <boost/asio.hpp>
int main(int argc, char** argv)
{
if (argc <= 2)
{
return 2;
}
try
{
boost::asio::ip::tcp::iostream ss(argv[1], argv[2]);
std::string send, recv;
while (getline(std::cin, send))
{
ss << send << std::endl;
getline(ss, recv);
std::cout << recv << std::endl;
}
}
catch(std::exception const& e)
{
std::cerr << e.what() << std::endl;
return 1;
}
return 0;
}
|





nu #7080() Rating-1/9=-0.11
TCPのechoクライアントを書いてください。
Windowsなら、Simple TCP/IP Servicesを起動してやれば、ローカルの確認用echo サーバとして使えます。
my_program localhost 7 < input_file > result_file
のようにしてリダイレクトを行った場合にも、result_fileがinput_fileの内容と一致するようにしてみてください。
[ reply ]