Helping ordinary people create extraordinary websites!
HOME TUTORIALS SCRIPTS WEB HOSTING BLOG FORUM
Get Our Newsletter
Email:

Understanding Sockets in Unix, NT, and Java

By Ken Nordby
2003-05-26


Client program (NT)

The C++ client program allows the user to send requests to the Unix man page server and see the responses on an NT machine. The client prompts for a Unix command string, such as "reboot," and formats a request message terminated by hex ff. When the client program starts up it goes through the necessary preliminary steps of creating a socket and connecting it to the man page server. By the time the prompt appears on the screen, the client socket is ready to transfer data over its connection with the server socket.

Environment
The C++ client program was developed on Windows NT 4.0 with Microsoft Visual C++ 5.0, and is executed within the Visual C++ environment as a command-line application.

Header

  • afx.h
    Required for Microsoft Foundation Class library
  • iostream.h
    Required for basic C++ input/output classes
  • winsock.h
    Required for winsock DLL.

Creating a Socket
Like the server program, the client program uses the socket() call to create a socket descriptor. The socket descriptor sd1 and the socket address structure sas1 are declared in the same manner as in the server program, which illustrates the similarity between the Windows implementation of sockets and the Unix implementation. The basic concepts of sockets communication are applicable across platforms. Microsoft documentation states that Windows sockets are based on the Unix sockets implementation in the BSD 4.3 release, and support both BSD-style socket routines plus extensions specific to Windows.

The chief difference in the Windows environment is the requirement for the winsock Dynamic Link Library (DLL). The corresponding header file, winsock.h, must be included in the source file, and the DLL must be available in the run-time environment. Note that winsock is the name of the original 16-bit Windows library, while wsock32 is the 32-bit version.

The winsock DLL must be initialized with a special function, WSAStartup(). The WSAStartup() call takes two arguments, a winsock version number and a pointer to a structure that stores winsock startup data. A zero return code indicates successful winsock startup. MAKEWORD is a C macro that puts the version number into the format required by this function.

The arguments to the socket() call in Windows are the same as they are in Unix-- AF_INET, SOCK_STREAM, and 0. These arguments request the creation of a socket that will use the Internet family of protocols for connection-oriented communication with the choice of protocol left up to the system. Unlike the server program, the client does not require multiple sockets. There is only one socket descriptor, sd1, which supports all communication with the server.

The initialization of the socket address structure for the client program is slightly different from the server program. As in the server program, the address family is set to AF_INET and the port number is set to 10001. However, the network addressing is different. Addressing in the server program is specified as INADDR_ANY, by which the server process tells the system it will accept messages from any network adapter on the machine. Addressing in the client program is specified as 9.37.195.88, which is the IP address of the server machine. Any outgoing messages sent through this socket will be addressed to this destination. inet_addr() is a support function that converts the dotted decimal representation of an IP address into the required internal format.

Connecting to the Server
When the client program issues the connect() call, the TCP/IP transport layer attempts to locate the target host at IP address 9.37.195.88 and establish a connection. Since the sample server program has already been started on the correct host and has already issued an accept() call, the connection can be set up immediately. Note that the client program does not have to specify its own IP address; the server program acquires this information from the connection request packet.

Exchanging Data with the Server
Once the server connection is functioning, the man page client program has access to the man page database on the remote Unix system. The client prompts the user for a man page request, which it transmits to the server with the send() call. Hex ff is appended to indicate end-of-transmission. After sending the request, the client program waits for a response with a recv() call. Note that the client receives up to 256 bytes of data for each recv() call rather than receiving bytes one at a time, like the server program. The client program parses the incoming data stream and displays an output line whenever it encounters a newline, formfeed, or carriage return character. When it finds a byte with the hex value ff, the client program recognizes the end of the server transmission, loops back, and prompts the user for another man page request. This continues indefinitely until the user enters "bye," which terminates the client program.

Code for client program (NT)



<xmp>
//Client Program - NT
#include <afx.h>
#include <iostream.h>
#include <winsock.h>
void main()

{
int returnCode,bytesRead,bytesWritten,requestSize,sd1,ctr;
struct sockaddr_in sas1;
struct WSAData wsa;
char charBuffer&lbracket.256&rbracket.;
CString displayLine;

//initialize winsock dll
returnCode=WSAStartup(MAKEWORD(1,1),&wsa);
if (returnCode!=0)
{
cerr << "WSAStartup not successful" << endl;
exit(1);
}
//create client socket
sd1=socket(AF_INET,SOCK_STREAM,0);
if (sd1<0)
{
cerr << "socket call not successful,;
sd1 = " <<sd1<< endl;
exit(1);
}
//initialize client socket structure; we know IP address and port number
sas1.sin_family=AF_INET;
sas1.sin_addr.S_un.S_addr=inet_addr("9.37.195.88");
sas1.sin_port=htons(10001);
//connect to server socket
returnCode=connect(sd1,(struct sockaddr *)&sas1,sizeof(sas1));
if (returnCode<0)
{
cerr << "connect call not successful,;
returnCode = "<<returnCode<<endl;
exit(1);
}
//loop indefinitely accepting requests from user
cout <<endl<<"Help for Unix Commands"<<endl<<endl;
while (1)
{
cout<<endl<<endl<<"Enter command: ";
cin >> charBuffer;
if (!strcmp(charBuffer,"bye"))
{
cout<<endl<<endl<<endl;
break;
}
CString string1(charBuffer);
string1+="\xff";
requestSize=string1.GetLength();
//send request to server
for (ctr=0;ctr<requestSize;ctr+=bytesWritten)
{
bytesWritten=send(sd1,string1,requestSize,0);
if (bytesWritten<0)
{
cerr << "send call not successful,;
bytesWritten = "<<bytesRead<<endl;
exit(1);
}
}
//receive response from server
cout<<endl<<endl;
displayLine="";
while (1)
{
bytesRead=recv(sd1,charBuffer,256,0);
if (bytesRead<0)
{
cerr << "recv call not successful,;
bytesRead = "<<bytesRead<<endl;
exit(1);
}
if (charBuffer&lbracket.0&rbracket.=='\xff') break;
for (ctr=0;ctr<bytesRead;ctr++)
{
if (charBuffer&lbracket.ctr&rbracket.=='\n'
&splitvbar.&splitvbar charBuffer&lbracket.ctr&rbracket.=='\f'
&splitvbar.&splitvbar charBuffer&lbracket.ctr&rbracket.=='\r')
{
charBuffer&lbracket.ctr&rbracket.='\0';
displayLine=charBuffer;
cout << displayLine << endl;
displayLine="";
}
else
{
displayLine+=charBuffer&lbracket.ctr&rbracket.;
}
}
} // end while
} // end while
return;
} //end main()
</xmp>

To cut and paste this code, click here.



Tutorial Pages:
» Understanding Sockets in Unix, NT, and Java
» Basic sockets concepts
» A simple example
» Sample sockets application
» Server program (Unix)
» Client program (NT)
» Client program (Java)
» Further study


First published by IBM DeveloperWorks


 | Bookmark
Related Tutorials:
» All about JAXP, Part 1
» Make Database Queries Without the Database
» Load List Values for Improved Efficiency
» 2 Ways To Implement Session Tracking
» A Simple Way to Read an XML File in Java
» Develop Aspect-Oriented Java Applications with Eclipse and AJDT