echo_client.C100600 6537 36 24147 7124172300 12004 0ustar iankusers /* Simple string echo client, modeled after W. Richard Stevens, UNIX Network Programming, fig. 5.4. */ /* To compile use the command line (on Windows NT 4.0) cl -DWIN32 -Tp simplec.c -o simples -link Wsock32.lib */ #ifdef WIN32 /* * WIN32 */ #define WIN32_LEAN_AND_MEAN #include #else /* * UNIX */ #include #include #include #include #include #include typedef int SOCKET; #define SOCKET_ERROR -1 #define INVALID_SOCKET -1 #define closesocket close #endif #include #include #include #include #include #include #define forever while(1) #define DEFAULT_PORT 5001 #define DEFAULT_PROTO SOCK_STREAM // TCP void Error(char *msg) { if (msg != NULL) { fprintf(stderr, "%s", msg ); } #ifdef WIN32 fprintf(stderr, " %d, %s", WSAGetLastError(), strerror(WSAGetLastError()) ); #else fprintf(stderr, " %s", strerror( errno ) ); #endif fprintf(stderr, "\n"); #ifdef WIN32 WSACleanup(); #endif exit( -1 ); } /* Error */ /* * WinInit * WinSock initialization. */ void WinInit(void) { #if WIN32 WSADATA wsaData; if (WSAStartup(0x202,&wsaData) == SOCKET_ERROR) { fprintf(stderr,"WSAStartup failed with error %d\n", WSAGetLastError()); WSACleanup(); exit( -1 ); } #endif } // WinInit class command_line { private: // class variables enum { BUF_SIZE = 256 }; const char *prog_name; unsigned short port; char *sys_name; char host_name_buf[ BUF_SIZE ]; private: // class functions void usage(void); void parse_comm_line( int argc, char *argv[] ); public: command_line(int argc, char *argv[] ); const unsigned short get_port(void) { return port; } const char *get_prog_name(void) { return prog_name; } const char *get_sys_name(void) { return sys_name; } }; // command_line command_line::command_line(int argc, char *argv[] ) { prog_name = argv[0]; if (gethostname(host_name_buf, sizeof(host_name_buf)) < 0) { Error("Could not get local host name: "); } sys_name = host_name_buf; // set defaults port = DEFAULT_PORT; parse_comm_line( argc, argv ); if (get_port() == 0){ usage(); } } // command_line constructor void command_line::usage(void) { fprintf(stderr,"Usage\n%s -n -p \n", prog_name); fprintf(stderr,"Where:\n\t example: -n foobar.com\n"); fprintf(stderr,"\t is port to send data on.\n"); fprintf(stderr,"Default port is 5001\n"); fprintf(stderr,"Default system is the local host. That is, we assume that\n"); fprintf(stderr,"the client and the server are running on the same system\n"); #ifdef WIN32 WSACleanup(); #endif exit(1); } /* Args: 1. program name 2,3. -n 4,5. -p */ void command_line::parse_comm_line( int argc, char *argv[] ) { const int MAX_ARGS = 5; int i; char *pArg; if (argc > 1 && argc <= MAX_ARGS ) { for(i = 1; i < argc; i++) { pArg = argv[i]; if ( (pArg[0] == '-') || (pArg[0] == '/') ) { switch( tolower( pArg[1] ) ) { // port argument case 'p': if (i+1 < argc) { i++; port = atoi(argv[i]); } break; // port argument case 'n': if (i+1 < argc) { i++; sys_name = argv[i]; } break; default: usage(); break; } // switch } else usage(); } } else usage(); } // parse_comm_line /* * Socket * */ SOCKET Socket(int family, int type, int protocol) { SOCKET conn_socket; conn_socket = socket(family, type, protocol ); /* Open a socket */ if (conn_socket < 0 ) { Error("Server: Error Opening socket: Error"); } return conn_socket; } // Socket /* * Connect * */ void Connect( SOCKET conn_socket, struct sockaddr *pServer, size_t data_size ) { assert( pServer != NULL ); if (connect(conn_socket, pServer, data_size ) == SOCKET_ERROR) { Error("connect() failed"); } } // Connect /* * get_hostent * */ struct hostent *get_hostent( const char *server_name ) { struct hostent *hp; // // Attempt to detect if we should call gethostbyname() or // gethostbyaddr() if (isalpha(server_name[0])) { /* server address is a name */ hp = gethostbyname(server_name); } else { /* Convert nnn.nnn address to a usable one */ unsigned int addr; addr = inet_addr(server_name); hp = gethostbyaddr((char *)&addr,4,AF_INET); } if (hp == NULL ) { char buf[128]; sprintf(buf, "Client: Cannot resolve address [%s]:", server_name); Error( buf ); } return hp; } // get_hostent /* * set_sockaddr * Initialize the sockaddr_in data structure */ void set_sockaddr( struct sockaddr_in *pSockAddr, int family, unsigned int port ) { memset( pSockAddr, 0, sizeof(struct sockaddr_in) ); pSockAddr->sin_family = AF_INET; pSockAddr->sin_port = htons(port); } // set_sockaddr void print_inet_addr( const char *pCh ) { int i; for (i = 0; i < 4; i++, pCh++) { printf("%d", *(unsigned char *)pCh ); if (i < 3) printf("."); } printf("\n"); } // print_inet_addr void print_hostent( struct hostent *pHostent ) { char **pAddrList; printf("pHostent->h_length = %d\n", pHostent->h_length ); printf("pHostent->h_addr = 0x%x\n", pHostent->h_addr ); print_inet_addr( pHostent->h_addr ); pAddrList = pHostent->h_addr_list; while (*pAddrList != NULL) { print_inet_addr( *pAddrList ); pAddrList++; } } // print_hostent int get_errno() { int err_ret; #ifdef WIN32 err_ret = WSAGetLastError(); #else err_ret = errno; #endif return err_ret; } /* get_errno */ /* Determine whether or not the error result is EINTR/WSAEINTR. This indicates that the socket read (recv) operation has been interruped and should be retried. The Dark Lord knows whether this actually works under Win32. WSAEINTR (win32) EINTR (unix) Interrupted function call. An asynchronous signal (such as SIGINT or SIGQUIT) was caught by the process during the execution of an interruptible function. If the signal handler performs a normal return, the interrupted function call will seem to have returned the error condition. */ int is_EINTR( int err_rslt ) { int rslt; rslt = 0; if (err_rslt != 0) { #ifdef WIN32 rslt = (err_rslt == WSAEINTR); #else rslt = (err_rslt == EINTR); #endif } return rslt; } /* is_EINTR */ int /* Write "n" bytes to a descriptor. */ writen(int fd, const void *vptr, size_t n) { const int FLAGS = 0; size_t nleft; int nwritten; const char *ptr; int err_rslt; ptr = (char *)vptr; nleft = n; while (nleft > 0) { if ( (nwritten = send(fd, ptr, nleft, FLAGS )) <= 0) { err_rslt = get_errno(); if (is_EINTR( err_rslt )) /* send was canceled by an external signal, try again */ nwritten = 0; else return(-1); /* error */ } nleft -= nwritten; ptr += nwritten; } return(n); } /* end writen */ static size_t my_read(int fd, char *ptr) { const int MAXLINE = 4096; /* max text line length */ const int FLAGS = 0; static int read_cnt = 0; static char *read_ptr; static char read_buf[MAXLINE]; int err_rslt; if (read_cnt <= 0) { do { read_cnt = recv(fd, read_buf, sizeof(read_buf), FLAGS); if (read_cnt < 0) { err_rslt = get_errno(); if (! is_EINTR( err_rslt ) ) { return(-1); } } else if (read_cnt == 0) return(0); } while (read_cnt <= 0); read_ptr = read_buf; } read_cnt--; *ptr = *read_ptr++; return(1); } /* my_read */ size_t readline(int fd, void *vptr, size_t maxlen) { int n, rc; char c, *ptr; ptr = (char *)vptr; for (n = 1; n < maxlen; n++) { if ( (rc = my_read(fd, &c)) == 1) { *ptr++ = c; if (c == '\n') break; /* newline is stored, like fgets() */ } else if (rc == 0) { if (n == 1) return(0); /* EOF, no data read */ else break; /* EOF, some data was read */ } else return(-1); /* error, errno set by read() */ } *ptr = 0; /* null terminate like fgets() */ return(n); } /* end readline */ int Readline(int fd, void *ptr, size_t maxlen) { size_t n; if ( (n = readline(fd, ptr, maxlen)) < 0) Error("readline error"); return(n); } void Writen(int fd, void *ptr, size_t nbytes) { if (writen(fd, ptr, nbytes) != nbytes) Error("writen error"); } char * Fgets(char *ptr, int n, FILE *stream) { char *rptr = NULL; if ( (rptr = fgets(ptr, n, stream)) == NULL && ferror(stream)) Error("fgets error"); return (rptr); } // Fgets char * Prompt_Fgets(char *ptr, int n, FILE *stream) { char *rptr = NULL; printf("str. out: "); rptr = Fgets( ptr, n, stream ); return rptr; } void Fputs(const char *ptr, FILE *stream) { if (fputs(ptr, stream) == EOF) Error("fputs error"); } // Fputs void str_cli( FILE *fd, int sockfd ) { const int MAXLINE = 4096; char sendline[ MAXLINE ], recvline[ MAXLINE ]; while (Prompt_Fgets(sendline, MAXLINE, fd) != NULL) { Writen( sockfd, sendline, strlen( sendline ) ); if (Readline( sockfd, recvline, MAXLINE) == 0) { Error("str_cli: server terminated prematurely"); } printf("str. in: "); Fputs( recvline, stdout ); } } // str_cli main( int argc, char *argv[] ) { int sockfd; struct sockaddr_in servaddr; command_line comm_line( argc, argv ); struct hostent *pHostent; WinInit(); if (comm_line.get_sys_name() == NULL) { // default the system name to the local host } memset( &servaddr, 0, sizeof( servaddr )); sockfd = Socket( AF_INET, SOCK_STREAM, 0); printf("client: system = %s, port = %d\n", comm_line.get_sys_name(), comm_line.get_port() ); set_sockaddr( &servaddr, AF_INET, comm_line.get_port() ); pHostent = get_hostent( comm_line.get_sys_name() ); // copy the four byte IP address from the hostent data structure // to the sin_addr field. memcpy(&servaddr.sin_addr, pHostent->h_addr, pHostent->h_length ); Connect( sockfd, (struct sockaddr *)&servaddr, sizeof( servaddr ) ); str_cli( stdin, sockfd ); exit( 0 ); } echo_server.C100600 6537 36 20272 7124172315 12035 0ustar iankusers /* Simple string echo server, modeled after W. Richard Stevens, UNIX Network Programming, fig. 5.2. */ /* To compile use the command line (on Windows NT 4.0) cl -DWIN32 -Tp simplec.c -o simples -link Wsock32.lib */ #ifdef WIN32 /* * WIN32 */ #define WIN32_LEAN_AND_MEAN #include #else /* * UNIX */ #include #include #include #include #include #include typedef int SOCKET; #define SOCKET_ERROR -1 #define INVALID_SOCKET -1 #define closesocket close #endif #include #include #include #include #include #include #define forever while(1) #define DEFAULT_PORT 5001 #define DEFAULT_PROTO SOCK_STREAM // TCP #define BACKLOG 5 void Error(char *msg) { if (msg != NULL) { fprintf(stderr, "%s", msg ); } #ifdef WIN32 fprintf(stderr, " %d, %s", WSAGetLastError(), strerror(WSAGetLastError()) ); #else fprintf(stderr, " %s", strerror( errno ) ); #endif fprintf(stderr, "\n"); #ifdef WIN32 WSACleanup(); #endif exit( -1 ); } /* Error */ /* * WinInit * WinSock initialization. */ void WinInit(void) { #if WIN32 WSADATA wsaData; if (WSAStartup(0x202,&wsaData) == SOCKET_ERROR) { fprintf(stderr,"WSAStartup failed with error %d\n", WSAGetLastError()); WSACleanup(); exit( -1 ); } #endif } // WinInit int get_errno() { int err_ret; #ifdef WIN32 err_ret = WSAGetLastError(); #else err_ret = errno; #endif return err_ret; } /* get_errno */ /* Determine whether or not the error result is EINTR/WSAEINTR. This indicates that the socket read (recv) operation has been interruped and should be retried. The Dark Lord knows whether this actually works under Win32. WSAEINTR (win32) EINTR (unix) Interrupted function call. An asynchronous signal (such as SIGINT or SIGQUIT) was caught by the process during the execution of an interruptible function. If the signal handler performs a normal return, the interrupted function call will seem to have returned the error condition. */ int is_EINTR( int err_rslt ) { int rslt; rslt = 0; if (err_rslt != 0) { #ifdef WIN32 rslt = (err_rslt == WSAEINTR); #else rslt = (err_rslt == EINTR); #endif } return rslt; } /* is_EINTR */ int /* Write "n" bytes to a descriptor. */ writen(int fd, const void *vptr, size_t n) { const int FLAGS = 0; size_t nleft; int nwritten; const char *ptr; int err_rslt; ptr = (char *)vptr; nleft = n; while (nleft > 0) { if ( (nwritten = send(fd, ptr, nleft, FLAGS )) <= 0) { err_rslt = get_errno(); if (is_EINTR( err_rslt )) /* send was canceled by an external signal, try again */ nwritten = 0; else return(-1); /* error */ } nleft -= nwritten; ptr += nwritten; } return(n); } /* end writen */ static size_t my_read(int fd, char *ptr) { const int MAXLINE = 4096; /* max text line length */ const int FLAGS = 0; static int read_cnt = 0; static char *read_ptr; static char read_buf[MAXLINE]; int err_rslt; if (read_cnt <= 0) { do { read_cnt = recv(fd, read_buf, sizeof(read_buf), FLAGS); if (read_cnt < 0) { err_rslt = get_errno(); if (! is_EINTR( err_rslt ) ) { return(-1); } } else if (read_cnt == 0) return(0); } while (read_cnt <= 0); read_ptr = read_buf; } read_cnt--; *ptr = *read_ptr++; return(1); } /* my_read */ size_t readline(int fd, void *vptr, size_t maxlen) { int n, rc; char c, *ptr; ptr = (char *)vptr; for (n = 1; n < maxlen; n++) { if ( (rc = my_read(fd, &c)) == 1) { *ptr++ = c; if (c == '\n') break; /* newline is stored, like fgets() */ } else if (rc == 0) { if (n == 1) return(0); /* EOF, no data read */ else break; /* EOF, some data was read */ } else return(-1); /* error, errno set by read() */ } *ptr = 0; /* null terminate like fgets() */ return(n); } /* end readline */ int Readline(int fd, void *ptr, size_t maxlen) { size_t n; if ( (n = readline(fd, ptr, maxlen)) < 0) Error("readline error"); return(n); } void Writen(int fd, void *ptr, size_t nbytes) { if (writen(fd, ptr, nbytes) != nbytes) Error("writen error"); } class command_line { private: // class variables const char *prog_name; unsigned short port; private: // class functions void usage(void); void parse_comm_line( int argc, char *argv[] ); public: command_line(int argc, char *argv[] ) { prog_name = argv[0]; // set defaults port = DEFAULT_PORT; parse_comm_line( argc, argv ); if (get_port() == 0){ usage(); } } const unsigned short get_port(void) { return port; } const char *get_prog_name(void) { return prog_name; } }; // command_line void command_line::usage(void) { fprintf(stderr,"Usage\n%s -p [port]\n", prog_name); fprintf(stderr,"Where:\n\tport is the port to listen on\n"); fprintf(stderr,"\tex: %s -p 6543\n", prog_name ); fprintf(stderr,"Default port is 5001\n"); #ifdef WIN32 WSACleanup(); #endif exit(1); } void command_line::parse_comm_line( int argc, char *argv[] ) { const int MAX_ARGS = 3; int i; char *pArg; if (argc > 1 && argc <= MAX_ARGS ) { for(i = 1; i < argc; i++) { pArg = argv[i]; if ( (pArg[0] == '-') || (pArg[0] == '/') ) { switch( tolower( pArg[1] ) ) { // port argument case 'p': if (i+1 < argc) { i++; port = atoi(argv[i]); } break; default: usage(); break; } // switch } else usage(); } } } // parse_comm_line /* * Socket * */ SOCKET Socket(int family, int type, int protocol) { SOCKET conn_socket; conn_socket = socket(family, type, protocol ); /* Open a socket */ if (conn_socket < 0 ) { Error("Server: Error Opening socket: Error"); } return conn_socket; } // Socket void Bind( SOCKET listen_socket, struct sockaddr *pSockAddr, int data_size) { // // bind() associates a local address and port combination with the // socket just created. This is most useful when the application is a // server that has a well-known port that clients know about in advance. // if (bind(listen_socket, pSockAddr, data_size ) == SOCKET_ERROR) { Error( "bind() failed with error" ); } } // Bind void Listen( SOCKET listen_socket, int backlog ) { if (listen(listen_socket, backlog) == SOCKET_ERROR) { Error( "listen() failed with error" ); } } // Listen /* * set_sockaddr * Initialize the sockaddr_in data structure */ void set_sockaddr( struct sockaddr_in *pSockAddr, int family, unsigned int port ) { memset( pSockAddr, 0, sizeof(struct sockaddr_in) ); pSockAddr->sin_family = AF_INET; pSockAddr->sin_addr.s_addr = htonl(INADDR_ANY); pSockAddr->sin_port = htons(port); } // set_sockaddr SOCKET Accept( SOCKET listen_socket, struct sockaddr *pFrom, int *pFrom_size ) { SOCKET msgsock; msgsock = accept(listen_socket, pFrom, pFrom_size ); if (msgsock == INVALID_SOCKET) { Error( "accept() error"); } return msgsock; } // Accept void Close( int fd ) { int close_rslt; #ifdef WIN32 close_rslt = closesocket( fd ); #else close_rslt = close( fd ); #endif if (close_rslt != 0) Error("Close error"); } // Close void str_echo( int connfd ) { const int MAXLINE = 4096; /* max text line length */ char line[ MAXLINE ]; int read_rslt; forever { if ((read_rslt = Readline( connfd, line, MAXLINE )) == 0) return; Writen(connfd, line, read_rslt); } } // str_echo int main( int argc, char *argv[] ) { int listenfd, connfd; int clilen; struct sockaddr_in cliaddr, servaddr; command_line comm_line( argc, argv ); WinInit(); listenfd = Socket( AF_INET, SOCK_STREAM, 0); printf("server: port = %d\n", comm_line.get_port() ); set_sockaddr( &servaddr, AF_INET, comm_line.get_port() ); Bind( listenfd, (struct sockaddr*)&servaddr, sizeof( servaddr) ); Listen( listenfd, BACKLOG ); forever { clilen = sizeof( cliaddr ); connfd = Accept( listenfd, (struct sockaddr*)&cliaddr, &clilen); str_echo( connfd ); Close( connfd ); } } // main