tcpsend.c
/*
* cc -g tcpsend.c -o ./tcpsend
* ./tcpsend 123.249.98.69:80 http.txt
*/
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h> /* struct sockaddr_in */
#include <errno.h>
#include <stdlib.h> /* malloc */
#include <string.h> /* strcpy */
extern int close(int fd);
#ifndef port_t
typedef unsigned short port_t;
#endif
#ifndef sock_t
typedef int sock_t;
#endif
#ifndef byte_t
typedef unsigned char byte_t;
#endif
typedef ssize_t (*buf_handler_t)(byte_t *buf, size_t len, void *param);
int bufferedFileReader(const char *path, size_t bufSize, buf_handler_t fn, void *param) {
FILE *fp = NULL;
size_t b = 0;
byte_t *buf = NULL;
if (0!=strncmp(path, "stdin", 5)) {
fp = fopen(path, "r");
if (NULL == fp) {
fprintf(stderr, "ERROR(%d) open %s: %s", errno, path, strerror(errno));
return errno;
}
} else {
fp = stdin;
}
buf = (byte_t *)malloc(bufSize);
if (NULL == buf) {
fprintf(stderr, "malloc(%lu) error", bufSize);
return -1;
}
do {
b = fread(buf, 1, bufSize, fp);
if (b < 1) {
break;
}
fn(buf, b, param);
} while (!feof(fp));
free(buf);
fclose(fp);
return 0;
}
sock_t tcp_connector(char ip[], port_t port) {
sock_t sockfd;
struct sockaddr_in addr;
int ret = 0;
sockfd = socket(AF_INET, SOCK_STREAM, 0);
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
addr.sin_addr.s_addr = inet_addr(ip);
ret = connect(sockfd, (struct sockaddr *)&addr, sizeof(addr));
if (ret != 0) {
close(sockfd);
return ret;
}
fprintf(stderr, "%s:%d connected.\r\n", ip, port);
return sockfd;
}
/**
* @param arg: "123.249.98.69:80"
* @param ip: "123.249.98.69"
* @param port: 80
*/
int parse_ip_port(char *arg, char ip[], port_t *port) {
*port = 0;
while (*arg != '\0' && *arg != ':') {
*ip++ = *arg++;
}
if (*arg=='\0') {
return -1;
}
arg++;
while (0x30 <= *arg && *arg < 0x40) {
*port *= 10;
*port += *arg - 0x30;
arg++;
}
return 0;
}
typedef struct {
sock_t sockfd;
FILE *out;
} ParamTrans_t;
ssize_t buf_send(byte_t *buf, size_t len, void *param) {
ParamTrans_t *p = (ParamTrans_t *)param;
return send(p->sockfd, buf, len, 0);
}
ssize_t buf_recv(byte_t *buf, size_t len, void *param) {
ParamTrans_t *p = (ParamTrans_t *)param;
ssize_t bytes = 0;
ssize_t br;
while (0 < (br = recv(p->sockfd, buf, len, MSG_WAITALL))) {
fwrite(buf, 1, br, p->out);
memset(buf, 0, br);
bytes += br;
}
return bytes;
}
#define ArraySize(a) (sizeof(a)/sizeof(a[0]))
int main(int argc, char *argv[])
{
char ip[16];
port_t port;
char src[256], dst[256];
ParamTrans_t param;
byte_t buf[128] = {0x00};
if (argc < 2) {
fprintf(stdout, "Usage: %s ip:port input.txt [output.txt]\n", argv[0]);
return 0;
}
if (argc < 3) { strcpy(src, "stdin"); } else { strncpy(src, argv[2], 256); }
if (argc < 4) { strcpy(dst, "stdout"); } else { strncpy(dst, argv[3], 256); }
/* 123.249.98.69:80 */
parse_ip_port(argv[1], ip, &port);
param.sockfd = tcp_connector(ip, port);
if (param.sockfd < 0) {
fprintf(stderr, "ERROR[%d] connect %s:%d %s\n", errno, ip, port, strerror(errno));
return -1;
}
if (0==strncmp(dst, "stdout", 6)) {
param.out = stdout;
} else {
param.out = fopen(dst, "w");
}
bufferedFileReader(src, 1024, buf_send, ¶m);
buf_recv(buf, ArraySize(buf), ¶m);
fclose(param.out);
close(param.sockfd);
return 0;
}