⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 main.c

📁 TCP/IP详解
💻 C
字号:
/*
 * Copyright (c) 1993 W. Richard Stevens.  All rights reserved.
 * Permission to use or modify this software and its documentation only for
 * educational purposes and without fee is hereby granted, provided that
 * the above copyright notice appear in all copies.  The author makes no
 * representations about the suitability of this software for any purpose.
 * It is provided "as is" without express or implied warranty.
 */

#include	"sock.h"

			/* define global variables */
char	*host;
char	*port;

int		bindport;			/* 0 or TCP or UDP port number to bind */
int		broadcast;			/* SO_BROADCAST */
int		cbreak;				/* set terminal to cbreak mode */
int		client = 1;			/* acting as client is the default */
int		crlf;				/* convert newline to CR/LF & vice versa */
int		debug;				/* SO_DEBUG */
int		dofork;				/* concurrent server, do a fork() */
char	foreignip[32];		/* foreign IP address, dotted-decimal string */
int		foreignport;		/* foreign port number */
int		halfclose;			/* TCP half close option */
int		keepalive;			/* SO_KEEPALIVE */
long	linger = -1;		/* 0 or positive turns on option */
int		listenq = 5;		/* listen queue for TCP Server */
int		nodelay;			/* TCP_NODELAY (Nagle algorithm) */
int		nbuf = 1024;		/* number of buffers to write (sink mode) */
int		pauseclose;			/* seconds to sleep after recv FIN, before close */
int		pauseinit;			/* seconds to sleep before first read */
int		pauselisten;		/* seconds to sleep after listen() */
int		pauserw;			/* seconds to sleep before each read or write */
int		reuseaddr;			/* SO_REUSEADDR */
int		readlen = 1024;		/* default read length for socket */
int		writelen = 1024;	/* default write length for socket */
int		recvdstaddr;		/* IP_RECVDSTADDR option */
int		rcvbuflen;			/* size for SO_RCVBUF */
int		sndbuflen;			/* size for SO_SNDBUF */
char   *rbuf;				/* pointer that is malloc'ed */
char   *wbuf;				/* pointer that is malloc'ed */
int		server;				/* to act as server requires -s option */
int		sourcesink;			/* source/sink mode */
int		udp;				/* use UDP instead of TCP */
int		urgwrite;			/* write urgent byte after this write */
int		verbose;

static void	usage(const char *);

int
main(int argc, char *argv[])
{
	int		c, fd;
	char	*ptr;

	if (argc < 2)
		usage("");

	opterr = 0;		/* don't want getopt() writing to stderr */
	while ( (c = getopt(argc, argv, "b:cf:hin:p:q:r:suvw:ABCDEFKL:NO:P:Q:R:S:U:")) != EOF) {
		switch (c) {
		case 'b':
			bindport = atoi(optarg);
			break;

		case 'c':			/* convert newline to CR/LF & vice versa */
			crlf = 1;
			break;

		case 'f':			/* foreign IP address and port#: a.b.c.d.p */
			if ( (ptr = strrchr(optarg, '.')) == NULL)
				usage("invalid -f option");

			*ptr++ = 0;					/* null replaces final period */
			foreignport = atoi(ptr);	/* port number */
			strcpy(foreignip, optarg);	/* save dotted-decimal IP */
			break;

		case 'h':			/* TCP half-close option */
			halfclose = 1;
			break;

		case 'i':			/* source/sink option */
			sourcesink = 1;
			break;

		case 'n':			/* number of buffers to write */
			nbuf = atol(optarg);
			break;

		case 'p':			/* pause before each read or write */
			pauserw = atoi(optarg);
			break;

		case 'q':			/* listen queue for TCP server */
			listenq = atoi(optarg);
			break;

		case 'r':			/* read() length */
			readlen = atoi(optarg);
			break;

		case 's':			/* server */
			server = 1;
			client = 0;
			break;

		case 'u':			/* use UDP instead of TCP */
			udp = 1;
			break;

		case 'v':			/* output what's going on */
			verbose = 1;
			break;

		case 'w':			/* write() length */
			writelen = atoi(optarg);
			break;

		case 'A':			/* SO_REUSEADDR socket option */
			reuseaddr = 1;
			break;

		case 'B':			/* SO_BROADCAST socket option */
			broadcast = 1;
			break;

		case 'C':			/* set standard input to cbreak mode */
			cbreak = 1;
			break;

		case 'D':			/* SO_DEBUG socket option */
			debug = 1;
			break;

		case 'E':			/* IP_RECVDSTADDR socket option */
			recvdstaddr = 1;
			break;

		case 'F':			/* concurrent server, do a fork() */
			dofork = 1;
			break;

		case 'K':			/* SO_KEEPALIVE socket option */
			keepalive = 1;
			break;

		case 'L':			/* SO_LINGER socket option */
			linger = atol(optarg);
			break;

		case 'N':			/* SO_NODELAY socket option */
			nodelay = 1;
			break;

		case 'O':			/* pause before listen(), before first accept() */
			pauselisten = atoi(optarg);
			break;

		case 'P':			/* pause before first read() */
			pauseinit = atoi(optarg);
			break;

		case 'Q':			/* pause after receiving FIN, but before close() */
			pauseclose = atoi(optarg);
			break;

		case 'R':			/* SO_RCVBUF socket option */
			rcvbuflen = atoi(optarg);
			break;

		case 'S':			/* SO_SNDBUF socket option */
			sndbuflen = atoi(optarg);
			break;

		case 'U':			/* when to write urgent byte */
			urgwrite = atoi(optarg);
			break;

		case '?':
			usage("unrecognized option");
		}
	}

		/* check for options that don't make sense */
	if (udp && halfclose)
		usage("can't specify -h and -u");
	if (udp && debug)
		usage("can't specify -D and -u");
	if (udp && linger >= 0)
		usage("can't specify -L and -u");
	if (udp && nodelay)
		usage("can't specify -N and -u");
	if (udp == 0 && broadcast)
		usage("can't specify -B with TCP");
	if (udp == 0 && foreignip[0] != 0)
		usage("can't specify -f with TCP");

	if (client) {
		if (optind != argc-2)
			usage("missing <hostname> and/or <port>");
		host = argv[optind];
		port = argv[optind+1];

	} else {
			/* If server specifies host and port, then local address is
			   bound to the "host" argument, instead of being wildcarded. */
		if (optind == argc-2) {
			host = argv[optind];
			port = argv[optind+1];
		} else if (optind == argc-1) {
			host = NULL;
			port = argv[optind];
		} else
			usage("missing <port>");
	}

	if (client)
		fd = cliopen(host, port);
	else
		fd = servopen(host, port);

	if (sourcesink)
		sink(fd);			/* ignore stdin/stdout */
	else
		loop(fd);			/* copy stdin/stdout to/from socket */

	exit(0);
}

static void
usage(const char *msg)
{
	err_msg(
"usage: sock [ options ] <host> <port>              (for client; default)\n"
"       sock [ options ] -s [ <IPaddr> ] <port>     (for server)\n"
"       sock [ options ] -i <host> <port>           (for \"source\" client)\n"
"       sock [ options ] -i -s [ <IPaddr> ] <port>  (for \"sink\" server)\n"
"options: -b n	bind n as client's local port number\n"
"         -c    convert newline to CR/LF & vice versa\n"
"         -f a.b.c.d.p  foreign IP address = a.b.c.d, foreign port# = p\n"
"         -h    issue TCP half close on standard input EOF\n"
"         -i    \"source\" data to socket, \"sink\" data from socket (w/-s)\n"
"         -n n  #buffers to write for \"source\" client (default 1024)\n"
"         -p n  #seconds to pause before each read or write (source/sink)\n"
"         -q n  size of listen queue for TCP server (default 5)\n"
"         -r n  #bytes per read() for \"sink\" server (default 1024)\n"
"         -s    operate as server instead of client\n"
"         -u    use UDP instead of TCP\n"
"         -v    verbose\n"
"         -w n  #bytes per write() for \"source\" client (default 1024)\n"
"         -A    SO_REUSEADDR option\n"
"         -B    SO_BROADCAST option\n"
"         -C    set terminal to cbreak mode\n"
"         -D    SO_DEBUG option\n"
"         -E    IP_RECVDSTADDR option\n"
"         -F    fork after connection accepted (TCP concurrent server)\n"
"         -K    SO_KEEPALIVE option\n"
"         -L n  SO_LINGER option, n = linger time\n"
"         -N    TCP_NODELAY option\n"
"         -O n  #seconds to pause after listen, but before first accept\n"
"         -P n  #seconds to pause before first read or write (source/sink)\n"
"         -Q n  #seconds to pause after receiving FIN, but before close\n"
"         -R n  SO_RCVBUF option\n"
"         -S n  SO_SNDBUF option\n"
"         -U n  enter urgent mode after write number n (source only)"
);

	if (msg[0] != 0)
		err_quit("%s", msg);
	exit(1);
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -