cs423-cotter1 example client program reference comer & stevens, chapter 7
TRANSCRIPT
cs423-cotter 2
Example Windows Client
• Develop a set of procedures that can be used by other programs to implement client / server.
int connectUDP (host, service)
int connectsock(host, service, “udp”)
[identify service, host, port]
[get a socket]
[connect to service / host / port]
[return socket number]
cs423-cotter 3
Example Windows ClientconnectTCP.c
#include <winsock.h>
SOCKET connectTCP (char *host, char *service){return connectsock (host, service, “tcp”);}
SOCKET connectUDP (char *host, char *service){return connectsock (host, service, “udp”);}
cs423-cotter 4
Example Windows Clientconnectsock.c
#include <stdlib.h>, <stdio.h>, <string.h>,<winsock.h>
SOCKET connectsock (char *host, char *service, char *transport){
struct hostent *phe;
struct servent *pse;
struct protoent *ppe;
struct sockaddr_in sin;
int s, type;
cs423-cotter 5
Example Windows Clientconnectsock.c
memset(&sin, 0, sizeof (sin));
sin.sin_family = AF_INET;
if (pse = getservbyname (service, transport) )
sin.sin_port = pse ->s_port;
else if ( (sin.sin_port = htons((u_short)atoi(service))) == 0)
errexit (“can’t get %s service\n”, service);
if (phe = gethostbyname (host) )
memcpy(&sin.sin_addr, phe->h_addr, phe->h_length);
else if ((sin.sin_addr.s_addr = inet_addr(host)) == INADDR_NONE)
errexit (“can’t get %s host\n”, host);
cs423-cotter 6
Example Windows Clientconnectsock.c
if ( (ppe = getprotobyname (transport) == 0)errexit (“can’t get %s protocol entry\n”,transport);
if (strcmp (transport, “tcp”) == 0) type = SOCK_STREAM;
else type = SOCK_DGRAM;if( (s = socket (PF_INET, type, ppe->p_proto)) == INVALID_SOCKET)
errexit (“Can’t create a socket: %d\n”, GetLastError());if (connect (s, (struct sockaddr *)&sin, sizeof(sin)) == SOCKET_ERROR)
errexit (“can’t connect to remote socket\n”);return s;}
cs423-cotter 7
Example client program
• Echo client (connection-oriented)
Establish a connection to server
while (user enters text)
send text to server
receive text back from server
display received message on screen
close connection & exit
cs423-cotter 8
tcpecho ( )#include <stdlib.h>,<stdio.h>,<string.h>,<winsock.h>
void TCPecho(const char *, const char *);
void errexit(const char *, ...);
SOCKET connectTCP(const char *, const char *);
#define LINELEN 128
#define WSVERS MAKEWORD(2, 0)
void main(int argc, char *argv[]) {
char *host = "localhost"; /* host to use if none supplied */
char *service = "echo"; /* default service name */
:
WSADATA wsadata;
if (WSAStartup(WSVERS, &wsadata) != 0)
errexit("WSAStartup failed\n");
TCPecho(host, service);
WSACleanup();
exit(0);
}
9
tcpecho ( ) – argument Switch#include <stdlib.h>,<stdio.h>,<string.h>,<winsock.h>voidTCPecho(), errexit(), connectTCP();#define LINELEN 128, WSVERS MAKEWORD(2, 0)void main(int argc, char *argv[]) {
char *host = "localhost"; /* host to use if none supplied */char *service = "echo"; /* default service name */
switch (argc) {case 1: break;case 3: service = argv[2]; //Fall Through!!case 2: host = argv[1]; break;default; printf (“Usage: %s [host[port]]\n”, argv[0]); exit(1);
}WSADATA wsadata;if (WSAStartup(WSVERS, &wsadata) != 0)
errexit("WSAStartup failed\n");TCPecho(host, service);WSACleanup();exit(0);
cs423-cotter 10
tcpecho (cont)
void TCPecho(const char *host, const char *service) {
char buf[LINELEN+1];/* buffer for one line of text */
SOCKET s; /* socket descriptor */
int cc, outchars, inchars; /* characters counts */
s = connectTCP(host, service);
while (fgets(buf, sizeof(buf), stdin)) {
buf[LINELEN] = '\0'; /* ensure line null-termination */
outchars = strlen(buf);
(void) send(s, buf, outchars, 0);
for (inchars = 0; inchars < outchars; inchars += cc) {
cc = recv(s, &buf[inchars], outchars-inchars, 0);
if (cc == SOCKET_ERROR)
errexit("socket recv failed: %d\n", GetLastError());
}fputs(buf, stdout);
} closesocket(s);
}
cs423-cotter 11
UDPecho.cpp
#include <stdlib.h>, <stdio.h>, <string.h>, <winsock.h>
void UDPecho(const char *, const char *);
void errexit(const char *, ...);
SOCKET connectUDP(const char *, const char *);
#define LINELEN 128
#define WSVERS MAKEWORD(2, 0)
void main(int argc, char *argv[])
{
char *host = "localhost", *service = "echo";
WSADATA wsadata;
if (WSAStartup(WSVERS, &wsadata))
errexit("WSAStartup failed\n");
UDPecho(host, service);
WSACleanup();
exit(0);
}
cs423-cotter 12
UDPecho.cppvoid UDPecho(const char *host, const char *service)
{
char buf[LINELEN+1];/* buffer for one line of text */
SOCKET s; /* socket descriptor */
int nchars; /* read count*/
s = connectUDP(host, service);
while (fgets(buf, sizeof(buf), stdin)) {
buf[LINELEN] = '\0'; /* ensure null-terminated */
nchars = strlen(buf);
(void) send(s, buf, nchars, 0);
if (recv(s, buf, nchars, 0) < 0)
errexit("recv failed: error %d\n",
GetLastError());
fputs(buf, stdout);
}
}
cs423-cotter 13
UDPecho_cnls.cpp
#include <stdlib.h>,<stdio.h>,<string.h>,<winsock.h>
….. // function prototypes, defines, etc.
void main(int argc, char *argv[]) {
char *host = "localhost", *service = "echo";
WSADATA wsadata;
switch (argc) {… } // test for command line params
if (WSAStartup(WSVERS, &wsadata))
errexit("WSAStartup failed\n");
UDPecho_cnls(host, service);
WSACleanup();
exit(0);
}
cs423-cotter 14
UDPecho_cnls.cpp (cont)
void UDPecho_cnls(const char *host, const char *service){
char buf[LINELEN+1];/*buffer for text */SOCKET s; /* socket descriptor */int nchars; /* read count*/struct hostent *phe; /* * host info entry */struct servent *pse; /* * service info entry */struct protoent *ppe; /* * protocol info entry */struct sockaddr_in sin; /* Internet endpoint addr*/int type, status; /* socket descriptor & type*/char *transport = "udp";/*Transport service name*/
cs423-cotter 15
UDPecho_cnls.cpp (cont)
memset(&sin, 0, sizeof(sin));sin.sin_family = AF_INET;
/* Map service name to port number */
if ( pse = getservbyname(service, transport) )
sin.sin_port = pse->s_port;
else if ( (sin.sin_port = htons((u_short)atoi(service)))== 0)
errexit("can't get \"%s\" service entry\n", service);
/*Map host name to IP address, dotted decimal(?)*/
if ( phe = gethostbyname(host) )
memcpy(&sin.sin_addr,phe->h_addr,phe->h_length);
cs423-cotter 16
UDPecho_cnls.cpp (cont)
else if( (sin.sin_addr.s_addr = inet_addr(host)) == INADDR_NONE)
errexit("can't get \"%s\" host entry\n", host);
printf("Server at %s\n",inet_ntoa(sin.sin_addr));
/* Map protocol name to protocol number */
if ( (ppe = getprotobyname(transport)) == 0)
errexit("Can't get \"%s\" entry\n", transport);
/* Use protocol to choose a socket type */
if (strcmp(transport, "udp") == 0)
type = SOCK_DGRAM;
else
type = SOCK_STREAM;
cs423-cotter 17
UDPecho_cnls.cpp (cont)
/* Allocate a socket */
s = socket(PF_INET, type, ppe->p_proto);
if (s == INVALID_SOCKET)
errexit("Socket error: %d\n", GetLastError());
printf("Enter data to send...\n");
while (fgets(buf, sizeof(buf), stdin)) {
buf[LINELEN] = '\0';/* ensure null-terminated */
nchars = strlen(buf);
status = sendto(s, buf, nchars, 0,
(struct sockaddr FAR *)&sin,sizeof(sin));
if (status == SOCKET_ERROR)
errexit("Sendto failed: %d\n", GetLastError());
cs423-cotter 18
UDPecho_cnls.cpp (cont)
printf ("We just sent a datagram\n");
if (recvfrom(s,buf,LINELEN,0,NULL,NULL) < 0)
errexit("recv failed: %d\n",GetLastError());
printf("We got back %d characters: ", nchars);
fputs(buf, stdout);
} /* end of while */
}/* end of UDPecho () */
cs423-cotter 19
UDPecho_cnls.cpp – v2
#include <iostream>#include <stdlib.h>#include <string.h>#include <winsock.h>
using namespace std;void UDPecho(const char *, const char *);#define LINELEN 128#define WSVERS MAKEWORD(2, 0)#define ARGSIZE 25
int main(int argc, char *argv[]){
char host[ARGSIZE] = "localhost";char service[ARGSIZE] = "12345";WSADATA wsadata;
cs423-cotter 20
UDPecho_cnls.cpp – v2switch (argc) {
case 1: break;
case 3: if (strlen(argv[2]) < ARGSIZE-1)
strcpy_s (service,strlen(argv[2])+1 ,argv[2]); else { cout << "Service name too long!!" << endl; exit (1); } /* FALL THROUGH */
case 2: if (strlen(argv[1]) < ARGSIZE-1)
strcpy_s (host,strlen(argv[1])+1 ,argv[1]); else { cout << "Service name too long!!" << endl; exit (1); }
break;
cs423-cotter 21
UDPecho_cnls.cpp – v2
default:cout << "Usage: UDPecho [host [port]]\n" << endl;exit(1);
}if (WSAStartup(WSVERS, &wsadata))
{ cout << "WSAStartup failed" << endl; exit(1); }
UDPecho(host, service);WSACleanup();return 0;
}
cs423-cotter 22
UDPecho_cnls.cpp – v2
void UDPecho(const char *host, const char *service){
char buf[LINELEN+1]; /* buffer for one line of text */SOCKET s; /* socket descriptor */int nchars; /* read count*/struct hostent *phe; /* pointer to host information entry */struct servent *pse; /* pointer to service information entry */struct protoent *ppe; /* pointer to protocol information entry */struct sockaddr_in sin; /* an Internet endpoint address */int type, status; /* socket descriptor and socket type */char *transport = "udp"; /* transport service name for port */
memset(&sin, 0, sizeof(sin));sin.sin_family = AF_INET;
cs423-cotter 23
UDPecho_cnls.cpp – v2
/* Map service name to port number */if ( pse = getservbyname(service, transport) )
sin.sin_port = pse->s_port;else if ( (sin.sin_port = htons((u_short)atoi(service)))== 0) {
cout << "Can't get \"" << service << "\" service entry" << endl; exit(1); } /* Map host name to IP address, allowing for dotted decimal */
if ( phe = gethostbyname(host) )memcpy(&sin.sin_addr, phe->h_addr, phe->h_length);
else if ( (sin.sin_addr.s_addr = inet_addr(host)) == INADDR_NONE) { cout << "Can't get \"" << host << "\" IP address "<< endl; exit(1); }
cs423-cotter 24
UDPecho_cnls.cpp – v2
cout <<"Our target server is at address " << inet_ntoa(sin.sin_addr) << endl;
/* Map protocol name to protocol number */if ( (ppe = getprotobyname(transport)) == 0) {
cout << "Can't get \"" << transport << "\" protocol entry "<< endl; exit(1); } /* Socket type is UDP*/
type = SOCK_DGRAM;
/* Allocate a socket */s = socket(PF_INET, type, ppe->p_proto);if (s == INVALID_SOCKET) {
cout << "Can't create socket" << endl; exit(1); }
cs423-cotter 25
UDPecho_cnls.cpp – v2
/* begin the data input / output loop... */cout << "Enter data to send..." << endl;while (cin.getline(buf,LINELEN)) { buf[LINELEN] = '\0'; /* ensure null-terminated */ nchars = strlen(buf); status = sendto(s, buf, nchars, 0, (struct sockaddr FAR *)&sin, sizeof(sin)); if (status == SOCKET_ERROR) {
cout << "Sendto failed ...: error " << GetLastError() << endl;exit(1);
} cout << "We just sent a datagram" << endl;
cs423-cotter 26
UDPecho_cnls.cpp – v2
if (recvfrom(s, buf, LINELEN, 0, NULL, NULL) < 0) {cout << "recv failed: error" << GetLastError() << endl;exit(1);
} if (strncmp(buf, "_quit", 5) == 0) {
cout << "Goodbye......" << endl;break;
} cout << "We got back the following " << nchars << " characters: " << endl; cout << buf << endl;} /* end of while */
}/* end of UDPecho () */
cs423-cotter 27
Sample Output
C: \udpecho_cnls\Debug>udpecho_cnls lab222c
Our target server is at address 134.193.2.253
Enter data to send...
This is my data
We just sent a datagram
We got back the following 16 characters: This is my data
This is another message
We just sent a datagram
We got back the following 24 characters: This is another message
^Z
C: \udpecho_cnls\Debug>