Hey!! Ahh, all day I've been trying to learn something new, so reading over tutorials I compiled my first socket app!! The only problem is, it isn't working the way I would like it to, and I was hoping you gyus could help me figure out the problems.. I appologize if it is a little messy at this time, I'm quite distrought and ready to pull my hair out so I didn't yet take the care to fine-ture it and organize the code.. I'll do that once I can get it to work and figure out how to manipulate these damn sockets lol.. For the time being, i want to work with Datagram sockets, not streaming.. Thanks..

My app: I want it to be simple and console-based, you have two options: To send or receive a message. If you choose to send, you enter the receiver's IP address and a message to send to them. If the message is received, it is returned with an asterisk (*) appended to the end of it. If you choose to receive, the app will wait until a return-request is received, then it will return the data with an asterisk (*) appended to the end of it.. Simple? Yea.. I will make it more advanced etc after I can get the following working properly, please help me with that:

// My First Internet Application
// By Matthew Cudmore, 2005

    #include <iostream>
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <arpa/inet.h>
    #include <unistd.h> // For gethostname

    #define MYPORT 4689
    #define QUEMAX 10

using namespace::std;

int main(void) {
	
	int sockfd, new_fd, sin_size;
	socklen_t sl = sizeof(struct sockaddr);
	struct sockaddr_in my_addr; // my address information
	struct sockaddr_in their_addr; // connector's address information
	
	// SOCK_STREAM or SOCK_DGRAM
	if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) == -1){
		// ERROR
		cout << "\n-- SOCKET error\n";
		return 0;
	}
	
	my_addr.sin_family = AF_INET;		// host byte order
	their_addr.sin_family = AF_INET;
	
	// Choose one method:
	// 1) my_addr.sin_port = htons(MYPORT); // short, network byte order
	// 2) my_addr.sin_port = htons(0);	// choose an unused port at random
	my_addr.sin_port = htons(MYPORT);	// short, network byte order
	their_addr.sin_port = htons(MYPORT);
	
	// Choose one method:
	// 1) my_addr.sin_addr.s_addr = inet_addr("10.12.110.57"); 
	// 2) inet_aton("10.12.110.57", &(my_addr.sin_addr));
	// 3) my_addr.sin_addr.s_addr = htonl(INADDR_ANY); // use my IP address
	my_addr.sin_addr.s_addr = htonl(INADDR_ANY); // use my IP address
	
	memset(&(my_addr.sin_zero), '\0', 8);	// zero the rest of the struct
	
	if (bind(sockfd, (struct sockaddr *)&my_addr,
	    sizeof(struct sockaddr)) == -1) {
		    // ERROR
		    cout << "\n-- BIND error\n";
		    return 0;
	    }
	
	// ###################################################################
	
	char Buffer[100];
	int BtsMvd;
	
	cout << "Simple sockets by Matthew Cudmore...\n";
	cout << "Your IP: " << inet_ntoa(my_addr.sin_addr) << "\n";
	
GetChoice:
	cout << "\nEnter choice action (x = exit, s = send, a = accept): ";
	cin.getline(Buffer, 99);
	
	if (Buffer[0] == 'x') {
		close (sockfd);
		return 0;
	} else if (Buffer[0] == 's') {
		cout << "Enter the IP of the receiving machine: ";
		cin.getline(Buffer, 99);
		their_addr.sin_addr.s_addr = inet_addr(Buffer);
		memset(&(their_addr.sin_zero), '\0', 8);
		cout << "Enter a message to send to the receiving machine: ";
		cin.getline(Buffer, 99);
		if ((BtsMvd = sendto(sockfd, Buffer, strlen(Buffer), 0,
		     (struct sockaddr *)&their_addr, sizeof(struct sockaddr))) != -1){
			cout << "\nMessage sent. Awaiting reply...";
		} else {
			cout << "\nMessage could not be sent.";
			goto GetChoice;
		}
		while (1) {
			if ((BtsMvd = recvfrom(sockfd, Buffer, strlen(Buffer), 0,
			     (struct sockaddr *)&their_addr, &sl)) == -1) {
				// ERROR
				cout << "\n-- recvfrom error\n";
				return 0;
			}
			if (BtsMvd) {
				if (Buffer[BtsMvd - 1] == '*') {
					cout << "\nReturn received.";
					break;
				} else {
					cout << "\nReturn-request ignored.";
				}
			}
		}
	} else if (Buffer[0] == 'a') {
		cout << "Waiting for incoming return-requests...";
		BtsMvd = 0;
		while (1) {
			if ((BtsMvd = recvfrom(sockfd, Buffer, strlen(Buffer), 0,
			     (struct sockaddr *)&their_addr, &sl)) == -1) {
			    // ERROR
			    cout << "\n-- recvfrom error\n";
			    return 0;
			}
			if (BtsMvd) break;
		}
		cout << "\nReturn-request received from: " << inet_ntoa(their_addr.sin_addr);
		BtsMvd = strlen(Buffer);
		Buffer[BtsMvd] = '*'; Buffer[BtsMvd + 1] = '\0';
		if ((BtsMvd = sendto(sockfd, Buffer, strlen(Buffer), 0,
		     (struct sockaddr *)&their_addr, sizeof(struct sockaddr))) > 0){
			cout << "\nA return (" << Buffer << ") has been sent back.";
		} else {
			cout << "\nCould not return request.";
		}
	}
	
	goto GetChoice;
	
	return 0;
}

The problems I've encountered: Can't retrieve my own IP address (I found out that was because INADDR_ANY is equal to zero).. When sending or waiting for data, the console kinda goes neutral and I can type and stuff when I shouldn't be able to.. It won't continue through the code, perhaps it's waiting for the receiving computer to respond with an ACK... Hmm, please heeeeellllppppp!!!! :cheesy:

Recommended Answers

All 3 Replies

Here is a running code. You will have to clean it up more.

// My First Internet Application
// By Matthew Cudmore, 2005

#include <iostream>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h> // For gethostname

#define MYPORT 4689
#define QUEMAX 10
#define BUFFER_LEN 100

#ifndef SOCKET_ERROR
#define SOCKET_ERROR -1
#endif
using namespace::std;

int main(void) 
{
	int sockfd, new_fd, sin_size;
	int sl = sizeof(struct sockaddr);
	struct sockaddr_in my_addr; // my address information
	struct sockaddr_in their_addr; // connector's address information

	// SOCK_STREAM or SOCK_DGRAM
	if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) == SOCKET_ERROR )
	{
		// ERROR
		cout << "\n-- SOCKET error\n";
		return 0;
	}

	my_addr.sin_family = AF_INET;		// host byte order
	their_addr.sin_family = AF_INET;

	// Choose one method:
	// 1) my_addr.sin_port = htons(MYPORT); // short, network byte order
	// 2) my_addr.sin_port = htons(0);	// choose an unused port at random
	my_addr.sin_port = htons(MYPORT);	// short, network byte order
	their_addr.sin_port = htons(MYPORT);

	// Choose one method:
	// 1) my_addr.sin_addr.s_addr = inet_addr("10.12.110.57"); 
	// 2) inet_aton("10.12.110.57", &(my_addr.sin_addr));
	// 3) my_addr.sin_addr.s_addr = htonl(INADDR_ANY); // use my IP address
	my_addr.sin_addr.s_addr = htonl(INADDR_ANY); // use my IP address

	memset(&(my_addr.sin_zero), '\0', 8);	// zero the rest of the struct

	if (bind(sockfd, (struct sockaddr *)&my_addr,sizeof(struct sockaddr)) ==  SOCKET_ERROR) 
	{
		// ERROR
		cout << "\n-- BIND error\n";
		return 0;
	}

	// ###################################################################

	char Buffer[BUFFER_LEN];
	int BtsMvd;

	cout << "Simple sockets by Matthew Cudmore...\n";
	cout << "Your IP: " << inet_ntoa(my_addr.sin_addr) << "\n";

GetChoice:
		cout << "\nEnter choice action (x = exit, s = send, a = accept): ";
		cin.getline(Buffer, 99);

		if (Buffer[0] == 'x') 
		{
			closesocket(sockfd);
			return 0;
		}
		else if (Buffer[0] == 's') 
		{
			cout << "Enter the IP of the receiving machine: ";
			cin.getline(Buffer, 99);
			their_addr.sin_addr.s_addr = inet_addr(Buffer);
			memset(&(their_addr.sin_zero), '\0', 8);
			cout << "Enter a message to send to the receiving machine: ";
			cin.getline(Buffer, 99);
			if ((BtsMvd = sendto(sockfd, Buffer, sizeof(Buffer), 0,(struct sockaddr *)&their_addr, sizeof(struct sockaddr))) != -1)
			{
				cout << "\nMessage sent. Awaiting reply...";
			}
			else
			{
				cout << "\nMessage could not be sent.";
				goto GetChoice;
			}
			while (1) 
			{
				if ((BtsMvd = recvfrom(sockfd, Buffer, sizeof(Buffer), 0,(struct sockaddr *)&their_addr, &sl)) == -1) 
				{
						// ERROR
						cout << "\n-- recvfrom error\n";
						return 0;
				}
				if ( BtsMvd ) 
				{
					BtsMvd = strlen(Buffer);
					if (Buffer[ BtsMvd - 1 ] == '*') 
					{
						cout << "\nReturn received.";
						break;
					} 
					else
					{
						cout << Buffer<<" \nReturn-request ignored.";
					}
				}
			}
		}
		else if (Buffer[0] == 'a') 
		{
			cout << "Waiting for incoming return-requests...";
			BtsMvd = 0;
			while (1) 
			{
				if ((BtsMvd = recvfrom(sockfd, Buffer, sizeof(Buffer), 0,(struct sockaddr *)&their_addr, &sl)) == SOCKET_ERROR) 
				{
					// ERROR
					cout << "\n-- recvfrom error\n";
					return 0;
				}
				if (BtsMvd)
				{
					break;
				}
			}
			cout << "\nReturn-request received from: " << inet_ntoa(their_addr.sin_addr);

			BtsMvd = strlen(Buffer);
			Buffer[ BtsMvd ] = '*';
			Buffer[ BtsMvd + 1 ] = '\0';

			their_addr.sin_family = AF_INET;
			their_addr.sin_port = htons(MYPORT);
			their_addr.sin_addr.s_addr =inet_addr( inet_ntoa(their_addr.sin_addr) ); 
			memset(&(their_addr.sin_zero), '\0', 8); // zero the rest of the struct

			if ((new_fd = socket(AF_INET, SOCK_DGRAM, 0)) == SOCKET_ERROR)
			{
				// ERROR
				cout << "\n-- SOCKET error\n";
				return 0;
			}

			if ((BtsMvd = sendto(new_fd, Buffer, sizeof(Buffer), 0,(struct sockaddr *)&their_addr, sizeof(struct sockaddr))) != SOCKET_ERROR )
			{
				cout << "\nA return (" << Buffer << ") has been sent back.";
			} 
			else 
			{
				cout << "\nCould not return request.";
			}
		}

		goto GetChoice;
		return 0;
}

The errors you made were not in the socket creation. This is what the Stevens Book say for bind at INADDR_ANY

But if we specify a wildcard IP address, the kernel does not choose the local IP address until either the socket is connected (TCP) or a datagram is sent on the socket (UDP).

Hence you see the

Your IP:  0.0.0.0

The errors were in specifying the amount of data to be received and sent using the recvfrom and sendto functions. You will understand while looking at my code.
Another thing, I am not good in Linux Programming, but I think there should be a way of determining the specific error that occurred under some function. e.g GetLastError in Windows. Find that. Then it will be easier to find out errors in your program. And if you are thinking of doing some serious network programming better to buy UNIX® Network Programming Volume by W.R. Stevens.

Alrightie then... I think all is well, and I've organized it a little more and taken care of that local IP-thing.. Now all that is left is to test it with someone running a Linux and see how it works, then improve it from there... Here is how I found my local IP:

char Buffer[100];
struct hostent *h; // MEEEEE

	if (gethostname(Buffer, sizeof(Buffer))) {
		// ERROR
		cout << "\n-- HOST error 1\n";
		return 0;
	}

	if ((h = gethostbyname(Buffer)) == 0x0) {
		// ERROR
		cout << "\n-- HOST error 2\n";
		return 0;
	}

	cout << "Your IP: " << inet_ntoa(*((struct in_addr *)h->h_addr)) << "\n";

Is that good enough? It shows me what I want to see, based on http://whatismyip.com/ but is there a better way to do this?? Oh, and when I am looking to recvfrom, the terminal will let me type freely while it waits to receive, actually the code *apparently* stops at that command until something is received, and it won't continue on until something actually is received lol.. Is there some way to fix this? I eitehr want to prevent the user from being able to type at the terminal while the wait is taking place, or better yet, cancel the wait after so many seconds, print "No return was received", then goto GetChoice.... Any ideas? thanks!! :mrgreen:

Hmm, on the top of my head the timeout thingie should be easiest to implement, I think. Atleast if you know soemthing about signaling, check man signal and man alarm (idea: signal( SIGALRM, IgnoreFunc ) ; alarm(timeout) ; recvfrom(...) ; check return code ; alarm(0) ; signal( SIGALRM, OldFunc ) )...
Atlernative could be asynchronus io with select (man select) or thread/processes using fork/pthreads...
I assume you could do something to skip input also, not sure how though, perhaps discard all input after you return from recvfrom ?

Well, I checked recvfrom man page and it also sugests poll for checking if data is availbile, how ever now it seems as if I am getting incoherent and any further ramblings are likely to be crapp so Ill stop (since I dont have paitence to reread what I've written)...
Btw the error value of functions can be found with errno (#include <errno.h> iirc)... and you can get a printing of the error reason with perror("description") but I think that function exists the program though...

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.