CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 15 of 15

Hybrid View

  1. #1
    Join Date
    Feb 2013
    Posts
    30

    simple client server app

    I have a client \ server project that I'm working on. Very entry level:

    I have to do the following
    • Server- Code in the listening port and start the server (I assume by executing the program...???)
    • Client - Enter code that prompts the user to add the ip address of the server and the port to be connected to
    • Upon entering that info- I assume, it will spit back a server connection verification to the client program.


    I have both the client code and the server code that I need to edit to obtain the desired results, but not sure where to look to do this:

    SERVER:
    HTML Code:
    #include <iostream>
    using namespace std;
    
    //#include <stdio.h>
    #include <winsock.h>
    #include <time.h>
    #include <string.h>
    
    // Function prototypes
    
    void DatagramServer(short nPort);
    void gettime( char tstr[], char server[] );
    
    // Helper macro for displaying errors
    
    #define PRINTERROR(s) cout << endl << s << ": " << WSAGetLastError() << endl;
    
    int main(int argc, char **argv)
    {
    	WORD wVersionRequested = MAKEWORD(1,1);			// Winsock version negotiation
    	WSADATA wsaData;								// WSAData data structure
    	int nRet;										// return code
    	short nPort;									// port number
    
    	//
    	// Check for port argument
    	//
    
    	if (argc != 2)
    	{
    		cout << "\nSyntax: Timesrvr PortNumber\n";
    		return 0;
    	}
    
    	nPort = atoi(argv[1]);
    	
    	//
    	// Initialize WinSock and check version
    	//
    	
    	nRet = WSAStartup(wVersionRequested, &wsaData);
    	
    	if (wsaData.wVersion != wVersionRequested)
    	{	
    		cout << "\nIncorrect WSA version... abort\n";
    		return 0;
    	}
    
    	//
    	// Do all the stuff a UDP datagram server does
    	//
    	
    	DatagramServer(nPort);
    	
    	//
    	// Release WinSock
    	//
    	
    	WSACleanup();
    }
    
    ////////////////////////////////////////////////////////////
    
    void DatagramServer(short nPort)
    {
    	SOCKET theSocket;				// Server Socket
    	SOCKADDR_IN saServer;			// Server details
    	SOCKADDR_IN saClient;			// Client details
    	int nRet;						// return code
    	int nLen;						// buffer length 
    	char szBuf[256];				// buffer space
    	char szSvr[256];				// buffer space
    
    	//
    	// Create a UDP/IP datagram socket
    	//
    
    	theSocket = socket(AF_INET,		// Address family
    					   SOCK_DGRAM,  // Socket type
    					   IPPROTO_UDP);// Protocol
    
    	if (theSocket == INVALID_SOCKET)
    	{
    		PRINTERROR("socket()");
    		return;
    	}
    	
    	//
    	// Fill in the address structure
    	//
    
    	saServer.sin_family = AF_INET;
    	saServer.sin_addr.s_addr = INADDR_ANY; // Let WinSock assign address
    	saServer.sin_port = htons(nPort);	   // Use port passed from user
    
    	//
    	// bind the name to the socket
    	//
    
    	nRet = bind(theSocket,				// Socket descriptor
    				(LPSOCKADDR)&saServer,  // Address to bind to
    				sizeof(struct sockaddr)	// Size of address
    				);
    
    	if (nRet == SOCKET_ERROR)
    	{
    		PRINTERROR("bind()");
    		closesocket(theSocket);
    		return;
    	}
    
    	//
    	// This isn't normally done or required, but in this 
    	// example we're printing out the port where the server
    	// is waiting so that you can connect the example client.
    	//
    	
    	nLen = sizeof(SOCKADDR);
    
    	nRet = gethostname(szSvr, sizeof(szSvr));
    
    	if (nRet == SOCKET_ERROR)
    	{
    		PRINTERROR("gethostname()");
    		closesocket(theSocket);
    		return;
    	}
    
    	//
    	// Show the server name and port number
    	//
    	
    	cout << "\nServer [" << szSvr << "] waiting on port " << nPort << endl;
    			
    	//
    	// Wait for data from the client
    	//
    
    	do
    	{
    		memset(szBuf, 0, sizeof(szBuf));
    		nRet = recvfrom(theSocket,			// Bound socket
    					szBuf,					// Receive buffer
    					sizeof(szBuf),			// Size of buffer in bytes
    					0,						// Flags
    					(LPSOCKADDR)&saClient,	// Buffer to receive client address 
    					&nLen);					// Length of client address buffer
    
    		//	
    		// Show that we've received some data
    		//
    	
    		cout << "\nData received: " << szBuf << endl;
    
    		//
    		// Get the system time
    		//
    
    		gettime(szBuf, szSvr);
    	
    		//
    		// Send data back to the client
    		//
    	
    		sendto(theSocket,					// Bound socket
    		   szBuf,							// Send buffer
    		   (int)strlen(szBuf),					// Length of data to be sent
    		   0,								// Flags
    		   (LPSOCKADDR)&saClient,			// Address to send data to
    		   nLen);							// Length of address
    	} while (TRUE);
    
    	
    	//
    	// And exit if user hits Control-C
    	//
    
    	closesocket(theSocket);
    	return;
    }
    
    void gettime( char tstr[], char server[] )
    {
    		struct tm newtime;
    		__time32_t aclock;
    
    
    		char buffer[32];
    		errno_t errNum;
    
    		_time32( &aclock );   // Get time in seconds.
    		_localtime32_s( &newtime, &aclock );   // Convert time to struct tm form.
    
    		// Print local time as a string.
    
    		errNum = asctime_s(buffer, 32, &newtime);
    		if (errNum)
    		{
    			printf("Error code returned from asctime_s function: %d", (int)errNum);
    		}
    
    		// Copy the result into the string to be returned
    
            sprintf_s(tstr, 256, "From the [%s] Server: %s",
                    server, buffer );
    
    }
    CLIENT
    HTML Code:
    #include <iostream>
    using namespace std;
    
    #include <string.h>
    #include <winsock.h>
    
    // Function prototype
    void DatagramClient(char *szServer, short nPort);
    
    // Helper macro for displaying error messages
    
    #define PRINTERROR(s) cout << endl << s << ": " << WSAGetLastError() << endl;
    
    ////////////////////////////////////////////////////////////
    
    int main(int argc, char **argv)
    {
    	WORD wVersionRequested = MAKEWORD(1,1);		// WORD data type for Winsock version
    	WSADATA wsaData;							// wsa data structure
    	int nRet;									// return value
    	short nPort;								// 16-bit port number
    
    	//
    	// Check for the host and port arguments
    	//
    
    	if (argc != 3)
    	{
    		cout << "Syntax: Timeclnt ServerName PortNumber\n\n";
    		return(0);
    	}
    
    	//
    	// extract the port number from the command line information
    	//
    
    	nPort = atoi(argv[2]);
    
    	//
    	// Initialize WinSock and check the version
    	//
    	
    	nRet = WSAStartup(wVersionRequested, &wsaData);
    
    	//
    	// check for the proper return value
    	//
    
    	if (wsaData.wVersion != wVersionRequested)
    	{	
    		cout << "Incorrect WSA version returned.\n";
    		return(0);
    	}
    
    	//
    	// Go do all the stuff a datagram client does
    	//
    
    	DatagramClient(argv[1], nPort);
    	
    	//
    	// Clean up and release WinSock
    	//
    
    	WSACleanup();
    }
    
    ////////////////////////////////////////////////////////////
    
    void DatagramClient(char *szServer, short nPort)
    {
    	char szBuf[256];				// data buffer
    	char szSvr[256];				// data buffer
    	int nRet;						// return value
    	int nFromLen;					// number of bytes returned
    	
    	LPHOSTENT lpHostEntry;			// LPHOSTENT network data structure
    	SOCKET	theSocket;				// Open the socket
    	SOCKADDR_IN saServer;			// SOCKET address data structure: contains information about IP, ip address and the port.
    
    
        //
        // Get local machine name
        //
    
    	nRet = gethostname(szSvr, sizeof(szSvr));
    	if (nRet == SOCKET_ERROR)
    	{
    		PRINTERROR("gethostname()");
    		return;
    	}
    
    	//
    	// output a little informational message
    	//
    
    	cout << endl << "Datagram Client ["  << szSvr 
    		 << "] sending to server ["
    		 << szServer << "] on port " << nPort << "...\n";
    
    	//
    	// Find the server
    	//
        
    	lpHostEntry = gethostbyname(szServer);
    
        if (lpHostEntry == NULL)
        {
            PRINTERROR("gethostbyname()");
            return;
        }
    
    	//
    	// Create a UDP/IP datagram socket
    	//
    
    	theSocket = socket(AF_INET,			// Address family
    					   SOCK_DGRAM,		// Socket type
    					   IPPROTO_UDP);	// Protocol
    
    	if (theSocket == INVALID_SOCKET)
    	{
    		PRINTERROR("socket()");
    		return;
    	}
    
    	//
    	// Fill in the address structure for the server
    	//
    
    	saServer.sin_family = AF_INET;
    	saServer.sin_addr = *((LPIN_ADDR)*lpHostEntry->h_addr_list);
    										// ^ Server's address
    	
    	saServer.sin_port = htons(nPort);	// Port number from command line
    
    	//
    	// Send data to the server
    	//
    
        sprintf_s(szBuf, 256, "From the Client [%s]", szSvr);
    	nRet = sendto(theSocket,				// Socket
    				  szBuf,					// Data buffer
    				  (int)strlen(szBuf),			// Length of data
    				  0,						// Flags
    				  (LPSOCKADDR)&saServer,	// Server address
    				  sizeof(struct sockaddr)); // Length of address
    
    	if (nRet == SOCKET_ERROR)
    	{
    		PRINTERROR("sendto()");
    		closesocket(theSocket);
    		return;
    	}
    
    	//
    	// Wait for the reply
    	//
    
    	memset(szBuf, 0, sizeof(szBuf));
    
    	nFromLen = sizeof(struct sockaddr);
    
    	recvfrom(theSocket,						// Socket
    			 szBuf,							// Receive buffer
    			 sizeof(szBuf),					// Length of receive buffer
    			 0,								// Flags
    			 (LPSOCKADDR)&saServer,			// Buffer to receive sender's address
    			 &nFromLen);					// Length of address buffer
    
    	if (nRet == SOCKET_ERROR)
    	{
    		PRINTERROR("recvfrom()");
    		closesocket(theSocket);
    		return;
    	}
    
    	//
    	// Display the data that was received
    	//
    	cout << szBuf << endl;
    	closesocket(theSocket);
    	return;
    }

  2. #2
    Join Date
    Apr 1999
    Posts
    27,449

    Re: simple client server app

    Quote Originally Posted by tmcfadden View Post
    I have a client \ server project that I'm working on. Very entry level:

    I have to do the following
    • Server- Code in the listening port and start the server (I assume by executing the program...???)
    • Client - Enter code that prompts the user to add the ip address of the server and the port to be connected to
    • Upon entering that info- I assume, it will spit back a server connection verification to the client program.


    I have both the client code and the server code that I need to edit to obtain the desired results, but not sure where to look to do this:
    Have you run the code you've posted? If not, then why not run it first to determine the flow of the program, instead of trying to eyeball multiple screensworth of code?

    Regards,

    Paul McKenzie

  3. #3
    Join Date
    Feb 2013
    Posts
    30

    Re: simple client server app

    Well, that's part of the problem.

    I KNOW that the code presented works, but what it does, I do not know.

    I've tried to run both the client and server program, but cannot see the results. I'm using Visual Studio 2010 and when I run (debug) the program, it flies through some stuff, a screen appears and disappears and that's it.
    When I put a break at the end of the program, it doesn't stop the program.

    I guess, I'm really looking for a starting block. Do I need breaks in a different location?
    Am I supposed to "step" through the program.

  4. #4
    Join Date
    Apr 1999
    Posts
    27,449

    Re: simple client server app

    Quote Originally Posted by tmcfadden View Post
    Well, that's part of the problem.

    I KNOW that the code presented works, but what it does, I do not know.

    I've tried to run both the client and server program, but cannot see the results. I'm using Visual Studio 2010 and when I run (debug) the program, it flies through some stuff, a screen appears and disappears and that's it.
    That is because you are not stepping into the program with F10.
    When I put a break at the end of the program, it doesn't stop the program.
    Why are you putting a break at the end of the program? You're supposed to place a breakpoint at the beginning of the main() function, since that is where the C++ program starts from. Or hit F10 to single-step through the program.

    Regards,

    Paul McKenzie

  5. #5
    Join Date
    Feb 2013
    Posts
    30

    Re: simple client server app

    Let me rephrase the question.

    I've stepped through both the server and client programs with F10 (both of which I provided earlier).

    What happens is that my instructor has created both programs, but each only confirms the number of arguments and outputs the following:

    SERVER PROGRAM


    Syntax: Timesrvr PortNumber

    CLIENT PROGRAM

    Syntax: Timeclnt ServerName PortNumber

    We're supposed to pass arguments that tell the server to use a port (example 2000)
    Then we need to pass arguments to the client that tell it to connect to the server at ip 127.0.0.1 port 2000

    So first I have to pass the arguments into the program. I know one way to do is in the file CONFIGURATION PROPERTIES | DEBUGGING | COMMAND ARGUMENTS in VB Studio 2010.
    So when I enter those arguments and run the program, the ARGC DOES, indeed, count up to the amount of arguments that I entered. However, those values are never output to screen.
    I didn't think I needed to create a variable to hold them though. I know the section of code that calls this up is here:
    HTML Code:
    	if (argc != 3)
    	{
    		cout << "Syntax: Timeclnt ServerName PortNumber\n\n";
    		return(0);
    	}
    Not sure how to do this. I'm assuming once you've entered those arguments, the client can then connect to the server ip address using the port number provided by the argument input.

    Does this make better sense?

  6. #6
    VictorN's Avatar
    VictorN is offline Super Moderator Power Poster
    Join Date
    Jan 2003
    Location
    Hanover Germany
    Posts
    20,395

    Re: simple client server app

    Quote Originally Posted by tmcfadden View Post
    Let me rephrase the question.

    I've stepped through both the server and client programs with F10 (both of which I provided earlier).
    Good!
    But what did you do after your first presses "F10" in both client and server applications? Did you repeat F10-presses to go on the next and next lines?
    Victor Nijegorodov

  7. #7
    Join Date
    Feb 2013
    Posts
    30

    Re: simple client server app

    Hey Victor.
    Yes. After each F10 selection, I take note of the output. I continue to select F10 until I get a console screen which displays the info listed in this block of code
    HTML Code:
    if (argc != 3)
    	{
    		cout << "Syntax: Timeclnt ServerName PortNumber\n\n";
    		return(0);
    	}
    which, as you can see, basically just outputs "Timeclint ServerName PortNumber"

  8. #8
    Join Date
    Apr 1999
    Posts
    27,449

    Re: simple client server app

    Quote Originally Posted by tmcfadden View Post
    Hey Victor.
    Yes. After each F10 selection, I take note of the output. I continue to select F10 until I get a console screen which displays the info listed in this block of code
    HTML Code:
    if (argc != 3)
    	{
    		cout << "Syntax: Timeclnt ServerName PortNumber\n\n";
    		return(0);
    	}
    which, as you can see, basically just outputs "Timeclint ServerName PortNumber"
    Do you know what "argc" is supposed to be, and more importantly, what it means? What is the argument count (argc) value when you get to that line of code? It obviously isn't 3, so you need to figure out what are the command-line arguments and exactly the number of arguments that need to be passed to the program.

    Regards,

    Paul McKenzie
    Last edited by Paul McKenzie; February 26th, 2013 at 02:40 PM.

  9. #9
    VictorN's Avatar
    VictorN is offline Super Moderator Power Poster
    Join Date
    Jan 2003
    Location
    Hanover Germany
    Posts
    20,395

    Re: simple client server app

    This part of code means:
    the program "Timeclnt" (obviously, the name of your client application) does expect from you to pass in exactly two command line arguments for the ServerName (IP address or pc-name) and socket port number.
    Did you pass theses two arguments? What exactly did you pass?
    Victor Nijegorodov

  10. #10
    Join Date
    Feb 2013
    Posts
    30

    Re: simple client server app

    right. That much I know. In fact, BOTH programs want me to pass arguments.
    The server side wants to know what port I'll be using.
    The client side wants to know the ip address of the server, as well as the port.

    The question is, how do I input those arguments into the code??
    So, the quick answer to your question is that I haven't passed any arguments into the program. I've tried, but I'm not seeing them.

  11. #11
    2kaud's Avatar
    2kaud is offline Super Moderator Power Poster
    Join Date
    Dec 2012
    Location
    England
    Posts
    7,822

    Re: simple client server app

    Have you compiled both programs successfully? To check that they are working:

    Open a console. Assuming the program for the server has been compiled to a program called server.exe. Make sure the console is at the folder where server.exe is located. Type server 2345 (where 2345 is the port number to use. Use the required port number). You should see something like

    Server [mycomp] waiting on port 2345

    where [...] will contain the name of your computer.

    Open another console. Assuming the client program has been compiled to a program called client.exe. Make sure the console is at the folder where this program is located. Type client <comp> 2345 where <comp> is the name of the computer shown from the server command above in the [] but not including the [] and 2345 is the port number used with the server command. You should see something like

    Datagram Client [mycomp] sending to server [mycomp] on port 2345...
    From the [mycomp] Server: Tue Feb 26 21:04:05 2013

    and on the server console you should see something like

    Data received: From the Client [mycomp]

    Once you have got this, then the programs are working. What else do you want from them?

  12. #12
    Join Date
    Feb 2013
    Posts
    30

    Re: simple client server app

    Hey 2kaud,
    As always, thanks for your valued input. You've instantly made this more clear.
    To answer your questions.
    - Yes - I ran both programs, but they're not "designed" to work initially. The point of the assignment is to make each program do just what you said it would do.

    - If you run the server.exe from the console as it is now, it returns this:

    Syntax: Timesrvr PortNumber

    - If you run the client.exe from the console as it is now, it returns this:

    Syntax: UDPTimeClient PortNumber

    So I have to add code snipits to the existing code to force the port number on the server, AND add the ipaddress and the port number to connect to on the client.

    So the question is, can I simply do this by entering arguments in the respective programs, or do I have to edit the code in some way?

  13. #13
    VictorN's Avatar
    VictorN is offline Super Moderator Power Poster
    Join Date
    Jan 2003
    Location
    Hanover Germany
    Posts
    20,395

    Re: simple client server app

    Quote Originally Posted by tmcfadden View Post
    So I have to add code snipits to the existing code to force the port number on the server, AND add the ipaddress and the port number to connect to on the client.

    So the question is, can I simply do this by entering arguments in the respective programs, or do I have to edit the code in some way?
    1. No. You do NOT need to add any code (at least, right now!) to let your programs run and communicate.

    2. Yes, you can "simply do this by entering arguments in the respective programs" either the way 2kaud described you or adding argument under Projects' properties/Debugging
    Victor Nijegorodov

  14. #14
    2kaud's Avatar
    2kaud is offline Super Moderator Power Poster
    Join Date
    Dec 2012
    Location
    England
    Posts
    7,822

    Re: simple client server app

    Yes - I ran both programs, but they're not "designed" to work initially. The point of the assignment is to make each program do just what you said it would do.
    I took your code and compiled it as you had posted it to produce two programs server.exe and client.exe. They work as I outlined in post #11. Just type server 2345 from the console. You must specify a port number (2345 in my example) following server

    d:\MyProgs>server 2345

    Server [mycomp] waiting on port 2345

    Then from another console prompt just type client mycomp 2345 (where mycomp is the name of the computer retured from server and 2345 is the same port number used with server

    d:\MyProgs>client mycomp 2345

    Datagram Client [mycomp] sending to server [mycomp] on port 2345...
    From the [mycomp] Server: Wed Feb 27 13:09:04 2013

    I just don't know what else I can say about this as the programs work from the command line as expected. I won't make any changes to the programs until this works for you the same as it works for me.

  15. #15
    Join Date
    Feb 2013
    Posts
    30

    Re: simple client server app

    Right, I don't expect any changes to be made.
    I just didn't know where to enter arguments into the program. I thought that there was some code that I'd have to add.

    I finally figured out that I can enter the arguments in the PROPERTIES | DEBUG area.
    Also figured out that multiple arguments CANNOT be separated by commas.

    It worked.
    Thanks again 2Kaud.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured