- 论坛徽章:
- 0
|
Request:
Write a tcp client that connects to a server and sends anything read from STDIN to the server and anything received from the server is sent to STDOUT.
/* Generic TCP client that reads from standard input
and forwards to a TCP socket. Also sends to stdout anything
received from the socket.
command line parameters identify the TCP server.
*/
#include stdio.h> /* standard C i/o facilities */
#include stdlib.h> /* needed for atoi() */
#include unistd.h> /* Unix System Calls */
#include sys/types.h> /* system data type definitions */
#include sys/socket.h> /* socket specific definitions */
#include netinet/in.h> /* INET constants and stuff */
#include arpa/inet.h> /* IP address conversion stuff */
#include netdb.h> /* Name lookups (gethostbyname) */
void tcp_client(int tcpsock);
/* The following must passed in on the command line:
name of the server (argv[1])
port number of the server (argv[2])
*/
int main( int argc, char **argv ) {
int sk;
struct sockaddr_in skaddr;
struct hostent *hp;
/* first - check to make sure there are 2 command line parameters
(argc=3 since the program name is argv[0])
*/
if (argc!=3) {
printf("Usage: client \n");
exit(0);
}
/* create a socket
IP protocol family (PF_INET)
TCP protocol (SOCK_STREAM)
*/
if ((sk = socket( PF_INET, SOCK_STREAM, 0 )) 0) {
perror("Problem creating socket");
exit(1);
}
/* fill in an address structure that will be used to specify
the address of the server we want to connect to
*/
skaddr.sin_family = AF_INET;
if ((hp = gethostbyname(argv[1]))!=0) {
/* Name lookup was successful - copy the IP address */
memcpy( &skaddr.sin_addr.s_addr, hp->h_addr, hp->h_length);
} else {
/* Name lookup didn't work, try converting from dotted decimal */
/*inet_aton is missing on Solaris - you need to use inet_addr! */
skaddr.sin_addr.s_addr = inet_addr(argv[1]);
if (skaddr.sin_addr.s_addr==-1) {
printf("Invalid IP address: %s\n",argv[1]);
exit(1);
}
}
skaddr.sin_port = htons(atoi(argv[2]));
/* attempt to establish a connection with the server */
if (connect(sk,(struct sockaddr *) &skaddr,sizeof(skaddr)) 0 ) {
perror("Problem connecting socket");
exit(1);
}
printf("Connected!\n");
/* Go handle the connection */
tcp_client(sk);
close(sk);
return(0);
}
/* multiplex client reads from stdin and a socket,
forwarding whatever is received from one source to the other.
*/
#define MAXMSG 1000
void tcp_client(int tcpsock) {
fd_set inputfds;
char buff[MAXMSG];
int i;
int max;
int watch_stdin = 1; /* Flag keeps track of status of stdin */
/* determine the highest number file descriptor we will use */
max = (tcpsock>STDIN_FILENO ? tcpsock : STDIN_FILENO);
/* do this forever */
while (1) {
FD_ZERO(&inputfds); /* clear out entire set */
FD_SET(tcpsock,&inputfds); /* add the socket to the set */
if (watch_stdin)
FD_SET(STDIN_FILENO,&inputfds); /* add stdin to the set */
/* call select - this blocks until there is something
to read on one of the file descriptors */
if (select(max+1,&inputfds,NULL,NULL,NULL)0) {
perror("select problem");
exit(1);
}
/* If STDIN has something - handle it */
if (FD_ISSET(STDIN_FILENO,&inputfds)) {
/* Read up to MAXMSG bytes from STDIN */
i = read(STDIN_FILENO,buff,MAXMSG);
if (i0) {
perror("Error reading from STDIN");
exit(1);
} else if (i==0) {
/* STDIN closed (EOF) - don't quit!
(we want to hang around and get stuff from socket)*/
watch_stdin=0;
} else {
/* Write whatever we got to the socket */
if (write(tcpsock,buff,i)0) {
perror("Error writing to socket");
exit(1);
}
}
}
/* If tcpsock has something - handle it */
if (FD_ISSET(tcpsock,&inputfds)) {
/* Read up to MAXMSG bytes from socket */
i = read(tcpsock,buff,MAXMSG);
if (i0) {
perror("Error reading from socket");
exit(1);
} else if (i==0) {
/* socket closed (EOF) - quit */
break;
} else {
/* Write whatever we got to STDOUT */
if (write(STDOUT_FILENO,buff,i)0) {
perror("Error writing to STDOUT!?!");
exit(1);
}
}
}
}
}
如果不明白的话,建议看看select()函数的功能。
本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u/21684/showart_453674.html |
|