-
February 25th, 2013, 02:38 PM
#1
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;
}
-
February 25th, 2013, 04:43 PM
#2
Re: simple client server app
Originally Posted by tmcfadden
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
-
February 25th, 2013, 06:02 PM
#3
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.
-
February 25th, 2013, 11:20 PM
#4
Re: simple client server app
Originally Posted by tmcfadden
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
-
February 26th, 2013, 12:31 PM
#5
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?
-
February 26th, 2013, 01:13 PM
#6
Re: simple client server app
Originally Posted by tmcfadden
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
-
February 26th, 2013, 01:29 PM
#7
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"
-
February 26th, 2013, 02:37 PM
#8
Re: simple client server app
Originally Posted by tmcfadden
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.
-
February 26th, 2013, 01:51 PM
#9
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
-
February 26th, 2013, 03:28 PM
#10
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.
-
February 26th, 2013, 04:20 PM
#11
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?
-
February 26th, 2013, 09:16 PM
#12
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?
-
February 27th, 2013, 02:08 AM
#13
Re: simple client server app
Originally Posted by tmcfadden
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
-
February 27th, 2013, 08:16 AM
#14
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.
-
February 27th, 2013, 09:26 AM
#15
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
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|