Programming Forums
User Name Password Register
 

RSS Feed
FORUM INDEX | TODAY'S POSTS | UNANSWERED THREADS | ADVANCED SEARCH

Reply
 
Thread Tools Display Modes
Old Nov 27th, 2005, 9:30 PM   #1
jayme
Professional Programmer
 
jayme's Avatar
 
Join Date: Nov 2005
Location: Canada
Posts: 495
Rep Power: 0 jayme is an unknown quantity at this point
Send a message via MSN to jayme
Network programming

I found a socket tutorial at this site... tutorial and decided i wanted to test out network programming.. so my first goal was to convert it mostly into C++, so now thats done and im just posting here for people to test it as it "grows up". Please feel free to drop a message in on the server by compiling this code, then follow the instructions bellow.

 #include <stdio.h>
#include <stdlib.h>
#include <winsock.h>
#include <strings.h>
#include <iostream.h>

#define MAXPENDING 5
#define BUFFER_SIZE 1024
#define EXIT_CALL " exit"

int main()
{
     int local_socket = 0, remote_socket = 0, menu_switch = 0, message_length = 0, remote_length = 0;
     unsigned short local_port = 0, remote_port = 0;
     struct sockaddr_in local_address, remote_address;
     WSADATA wsa_data;
     char message[BUFFER_SIZE], remote_ip[32];

     cout << "Send data to server[1]\n";
     cout << "Listen for data as server[2]\n";
     cout << "Make your selection: ";
do {
        cin.clear ();
        if (cin.sync ());
        cin >> menu_switch;
        if (!cin.good ()) cout << "You must enter an integer: ";
        } while (menu_switch == 0);


     cout << "Enter local port to use: ";
do {
        cin.clear ();
        if (cin.sync ());
        cin >> local_port;
        if (!cin.good ()) cout << "You must enter a port: ";
        } while (local_port == 0);

     if (WSAStartup(MAKEWORD(2, 0), &wsa_data) != 0)
     {
          cout << "WSAStartup() failed\n";
          return (1);
     }

     if ((local_socket = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
     {
          cout << "socket() failed\n";
          return(1);
     }

     /* Construct local address structure */
     memset(&local_address, 0, sizeof(local_address)); /* Zero out structure */
     local_address.sin_family = AF_INET; /* Internet address family */
     local_address.sin_addr.s_addr = htonl(INADDR_ANY); /* Any incoming interface */
     local_address.sin_port = htons(local_port); /* Local port */

     /* Bind to the local address */
     if (bind(local_socket, (struct sockaddr *) &local_address, sizeof(local_address)) < 0)
     {
          cout << "bind() failed\n";
          return(1);
     }

     switch (menu_switch)
     {
          case 1:
               cout << "Enter server IP: ";
do {
        cin.clear ();
        if (cin.sync ());
        cin >> remote_ip;
        if (!cin.good ()) cout << "You must enter an ip: ";
        } while (remote_ip == 0);
fflush(stdin);
               cout << "Enter server Port: ";
do {
        cin.clear ();
        if (cin.sync ());
        cin >> remote_port;
        if (!cin.good ()) cout << "You must enter a port: ";
        } while (remote_port == 0);
fflush(stdin);
               if ((remote_socket = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
               {
                    cout << "socket() failed";
                    return(1);
               }

               memset(&remote_address, 0, sizeof(remote_address)); /* Zero out structure */
               remote_address.sin_family = AF_INET; /* Internet address family */
               remote_address.sin_addr.s_addr = inet_addr(remote_ip); /* Server IP address */
               remote_address.sin_port = htons(remote_port); /* Server port */

               if (connect(remote_socket, (struct sockaddr *) &remote_address, sizeof(remote_address)) < 0)
               {
                    cout << "connect() failed";
                    return(1);
               }

               do
               {
                    memset(&message, 0, BUFFER_SIZE);
                    cout << "Enter message to send: ";
                    gets(message);
                    fflush(stdin);

                    message_length = (strlen(message));

                    if (send(remote_socket, message, message_length, 0) != message_length)
                    {
                         cout << "send() failed";
                         return(1);
                    }
               }
               while(strcmp(message, EXIT_CALL));
          break;
          case 2:
               /* Mark the socket so it will listen for incoming connections */
               if (listen(local_socket, MAXPENDING) < 0)
               {
                    cout << "listen() failed\n";
                    return(1);
               }

               remote_length = sizeof(remote_address);
               for(;;)
               {
                    /* Accepts an incoming connection when one is detected */
                    if((remote_socket = accept(local_socket, (struct sockaddr *) &remote_address, &remote_length) ) < 0)
                    {
                         cout << "accept() failed\n";
                         return(1);
                    }
                    else
                    {
                         break;
                    }
               }

               do
               {
                    memset(&message, 0, BUFFER_SIZE);
                    /*receive the message from the client*/
                    if((message_length = recv(remote_socket, message, BUFFER_SIZE, 0)) < 0)
                    {
                         cout << "recv() failed\n";
                         return(1);
                    }
                    cout << "From client " << inet_ntoa(remote_address.sin_addr) <<": " << message << endl;
               }
               while(strcmp(remote_ip, EXIT_CALL));
          break;
     }

     WSACleanup(); /* Cleanup Winsock */
     closesocket(local_socket);
     closesocket(remote_socket);
     system("pause");
     return(0);
}

1. Compile then run the program
2. Send data to server[1]
3. Enter Local port to use: 51
4. Enter server IP: 70.80.252.72
5. Enter server Port: 50
__________________

Quote:
Originally Posted by Mohamed Jihad
Durka durka!
Due to incorrect calculations during the middle ages, our calendar actually begins a few years after Jesus' birth. Thus the real 6/6/6 happened a few years back. The world already ended and you missed it.

Download Code::Blocks now!
jayme is offline   Reply With Quote
Old Nov 27th, 2005, 10:02 PM   #2
jayme
Professional Programmer
 
jayme's Avatar
 
Join Date: Nov 2005
Location: Canada
Posts: 495
Rep Power: 0 jayme is an unknown quantity at this point
Send a message via MSN to jayme
edit time expired anyways,
I noticed that once anyone closes their client, the server closes too..
If anyone can look above and tell me how i would be able to close the client, without the server closing.. ive tried to get rid of the exit_call command and a few other things, not too sure how to do it though .. any help?
__________________

Quote:
Originally Posted by Mohamed Jihad
Durka durka!
Due to incorrect calculations during the middle ages, our calendar actually begins a few years after Jesus' birth. Thus the real 6/6/6 happened a few years back. The world already ended and you missed it.

Download Code::Blocks now!
jayme is offline   Reply With Quote
Old Nov 27th, 2005, 10:19 PM   #3
Animatronic
Programmer
 
Join Date: Jun 2005
Posts: 99
Rep Power: 4 Animatronic is on a distinguished road
revc() will return 0 if the connection has closed at the other end, it will then return <0 if you try to call recv() on the closed socket again. So you need to handle the 0 case to make sure your not trying to recv() on a closed socket.
Animatronic is offline   Reply With Quote
Old Nov 28th, 2005, 8:22 AM   #4
jayme
Professional Programmer
 
jayme's Avatar
 
Join Date: Nov 2005
Location: Canada
Posts: 495
Rep Power: 0 jayme is an unknown quantity at this point
Send a message via MSN to jayme
i dont quite understand, i tried changing the < 0 and 0 flags around but it wouldnt exactly help, it would just close the server when i tried to send a message..
__________________

Quote:
Originally Posted by Mohamed Jihad
Durka durka!
Due to incorrect calculations during the middle ages, our calendar actually begins a few years after Jesus' birth. Thus the real 6/6/6 happened a few years back. The world already ended and you missed it.

Download Code::Blocks now!
jayme is offline   Reply With Quote
Old Nov 28th, 2005, 4:01 PM   #5
nindoja
Programmer
 
Join Date: Jun 2005
Posts: 92
Rep Power: 4 nindoja is on a distinguished road
Basically, what is happening is that recv is failing, so if you are checking for a return value of SOCKET_ERROR, and if found then exiting, the program finds SOCKET_ERROR and then exits. There are two solutions. One is to write using asynchronous (non-blocking) sockets, which would allow for multiple connections at once, assuming it is writen right. The other solution is make a while(1) loop starting before the call to listen, and ending after you close the connection. Then check if the return value of recv() is 0 and if so, close the socket, and go back to the top of the loop. In my opinion, the first solution is better, but it will require more time to be put into the program.

P.S. I haven't tried the second solution, so I'm not sure how well it would work, or if it WinSock would mess with the socket to the point where it wouldn't work.
nindoja is offline   Reply With Quote
Old Dec 3rd, 2005, 7:53 PM   #6
jayme
Professional Programmer
 
jayme's Avatar
 
Join Date: Nov 2005
Location: Canada
Posts: 495
Rep Power: 0 jayme is an unknown quantity at this point
Send a message via MSN to jayme
What im asking is how do i set recv() back to 1 or higher each loop? what do i do?
__________________

Quote:
Originally Posted by Mohamed Jihad
Durka durka!
Due to incorrect calculations during the middle ages, our calendar actually begins a few years after Jesus' birth. Thus the real 6/6/6 happened a few years back. The world already ended and you missed it.

Download Code::Blocks now!
jayme is offline   Reply With Quote
Old Dec 3rd, 2005, 8:22 PM   #7
Animatronic
Programmer
 
Join Date: Jun 2005
Posts: 99
Rep Power: 4 Animatronic is on a distinguished road
Excuse the horrible pseudo code, but this is how I would lay out a multiple client server (with non-blocking sockets):

	while( true )
	{
		if( ListenSocket.Listen() != error ) // accept new clients
		{
			ClientList.Add(  ListenSocket.Accept() );
		}

		for each( Socket s in ClientList )
		{
			int recvValue;
			if( (recvValue = s.Recv( data )) > 0 )
			{
				//process command
			}
			else
			{
				if( recvValue == 0 ) //client has quit
				{
					s.Close();
					ClientList.Remove( s );
				}
				else
				{
					// process error
				}
			}
		}
	}
Animatronic is offline   Reply With Quote
Old Dec 3rd, 2005, 11:18 PM   #8
nindoja
Programmer
 
Join Date: Jun 2005
Posts: 92
Rep Power: 4 nindoja is on a distinguished road
@jayme: you can't set the return value of recv, the function determines that. Recv( is specific to a certain socket, so if the user closes the program then recv will always fail, so you need to close that socket and reinitilize it with the listen and accept functions. What you need to do is place a while(1) before your call to the listen function, and end the loop after your do ... while that receives data from the user. Then, instead of returning 1 when recv( fails, close the socket and then put continue;, so you can go to the top of the loop and listen for another user. Then the program continues as normal.
nindoja is offline   Reply With Quote
Old Dec 3rd, 2005, 11:27 PM   #9
jayme
Professional Programmer
 
jayme's Avatar
 
Join Date: Nov 2005
Location: Canada
Posts: 495
Rep Power: 0 jayme is an unknown quantity at this point
Send a message via MSN to jayme
ahh.. Well then i was trying to put a loop in the wrong area.. thanks
__________________

Quote:
Originally Posted by Mohamed Jihad
Durka durka!
Due to incorrect calculations during the middle ages, our calendar actually begins a few years after Jesus' birth. Thus the real 6/6/6 happened a few years back. The world already ended and you missed it.

Download Code::Blocks now!
jayme is offline   Reply With Quote
Old Dec 4th, 2005, 8:47 AM   #10
Symptom
Newbie
 
Symptom's Avatar
 
Join Date: Sep 2005
Posts: 28
Rep Power: 0 Symptom is on a distinguished road
It very common to handle every incoming connection to the server, not in the parent process, but with child processes using
fork();
That way when the client is done with the server, the child process ends and, furthermore, the client is able to handle more than one connections simultaneously.
If you're programming under windows though, I don't know if you have a POSIX-like environment that supports these system calls...
__________________
The geeks shall inherit the earth.
Symptom is offline   Reply With Quote
Reply

Bookmarks

« Previous Thread in Forum | Next Thread in Forum »

Currently Active Users Viewing This Thread: 1 (0 members and 1 guests)
 
Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Forum Jump




DaniWeb IT Discussion Community
All times are GMT -5. The time now is 2:46 AM.

Powered by vBulletin® Version 3.7.0, Copyright ©2000 - 2008, Jelsoft Enterprises Ltd.
Copyright ©2007 DaniWeb® LLC