20-第一个netcat的实现
代码
recipes/netcat.cc at master · chenshuo/recipes (github.com)
#include "Acceptor.h"
#include "InetAddress.h"
#include "TcpStream.h"
#include <thread>
#include <string.h>
#include <unistd.h>
// 读n字节
int write_n(int fd, const void* buf, int length)
{
int written = 0;
while (written < length)
{
int nw = ::write(fd, static_cast<const char*>(buf) + written, length - written);
if (nw > 0)
{
written += nw;
}
else if (nw == 0)
{
break; // EOF
}
else if (errno != EINTR)
{
perror("write");
break;
}
}
return written;
}
void run(TcpStreamPtr stream)
{
// 子线程:负责从socket读数据,并将数据写到stdout
// Caution: a bad example for closing connection
std::thread thr([&stream] () {
char buf[8192];
int nr = 0;
while ( (nr = stream->receiveSome(buf, sizeof(buf))) > 0)
{
int nw = write_n(STDOUT_FILENO, buf, nr);
if (nw < nr)
{
break;
}
}
::exit(0); // should somehow notify main thread instead
});
// 主线程:负责从stdin读数据,并将数据写到socket
char buf[8192];
int nr = 0;
while ( (nr = ::read(STDIN_FILENO, buf, sizeof(buf))) > 0)
{
int nw = stream->sendAll(buf, nr);
if (nw < nr)
{
break;
}
}
stream->shutdownWrite();
thr.join();
}
int main(int argc, const char* argv[])
{
if (argc < 3)
{
printf("Usage:\n %s hostname port\n %s -l port\n", argv[0], argv[0]);
return 0;
}
int 