Учора я розмістив запит на перегляд коду . Після перегляду коду і відгуків, і після деякого сну, я вирішив, що можу зробити краще. Насправді я ввійшов у систему з наміром видалити це питання саме тоді, коли був опублікований перший огляд; так що я застряг з ним.
Це майже така ж програма, але вона є результатом набагато більше зусиль. Вона навіть включає в себе річ, яку я раніше не використовував: select
. Для використання програми і попередньої програми користувач надає два аргументи: цільовий IP і цільовий порт. На відміну від останньої програми, ця програма завершується за допомогою ctrl c .
#include
#include
#include
#include
#include
#include
#include
#define BUFLEN 1024
#define STDIN 0
#define STDOUT 1
void sigint_handle(int dummy);
int connect_to(char *host, int port);
int transfer(int fd_in, char *buf, int buf_len, int fd_out);
// boolean flag for program continuation
volatile int run = 1;
// entry point of linux ELF
int main(int args, char **argv) {
int sd, ret_val = 0;
fd_set fds;
struct timeval tv;
char buffer[BUFLEN];
assert(args == 3);
signal(SIGINT, sigint_handle);
sd = connect_to(argv[1], atoi(argv[2]));
FD_ZERO(&fds);
tv.tv_sec = 0;
tv.tv_usec = 10000;
while (run) {
FD_SET(STDIN, &fds);
FD_SET(sd, &fds);
ret_val = select(sd + 1, &fds, NULL, NULL, &tv);
if (FD_ISSET(STDIN, &fds))
ret_val = transfer(STDIN, buffer, BUFLEN, sd);
else if (FD_ISSET(sd, &fds))
ret_val = transfer(sd, buffer, BUFLEN, STDOUT);
assert(ret_val == 0);
}
close(sd);
return 0;
}
// SIGINT handler
void sigint_handle(int dummy) {
run = 0;
}
// a very picky connect to tcp host function
int connect_to(char *host, int port) {
struct sockaddr_in addr;
int sd = socket(AF_INET, SOCK_STREAM, 0);
memset(&addr, 0, sizeof(addr));
assert(sd > -1);
addr.sin_family = AF_INET;
assert(inet_pton(AF_INET, host, &addr.sin_addr) > 0);
addr.sin_port = htons(port);
assert(connect(sd, (struct sockaddr *)&addr, sizeof(addr)) > -1);
return sd;
}
// transfer function - basically a one time pipe
int transfer(int fd_in, char *buf, int buf_len, int fd_out) {
int len = read(fd_in, buf, buf_len);
return len - write(fd_out, buf, len);
}
Я маю відзначити, що це не означає, що це зручно для користувачів. Він призначений для виконання однієї конкретної задачі як підпроцесу, і паніки в іншому випадку; знову за допомогою ctrl c для виходу.
import subprocess
import signal
import os
import socket
def dostuff():
host = socket.gethostbyname("google.com")
proc = subprocess.Popen(["./client " + host + " 80"],
stdout=subprocess.PIPE, shell=True,
stdin=subprocess.PIPE)
global pid
pid = proc.pid
proc.stdin.write("GET /\n\n")
while proc.poll() is None:
print proc.stdout.readline()
if __name__ == "__main__":
try: dostuff()
except: os.kill(pid, signal.SIGINT)