LinuxQuestions.org
Welcome to the most active Linux Forum on the web.
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices

Reply
 
Search this Thread
Old 05-01-2004, 06:45 PM   #1
AquamaN
Member
 
Registered: Oct 2002
Location: Ohio, USA
Distribution: OS X 10.4.8, Ubuntu 6.10
Posts: 146

Rep: Reputation: 15
sockaddr_in and sockaddr


Ok, I'm writing a simple client server program to do a CRC check on a file the client is going to send. Just one transfer and it's done.. So I set out and wrote them both almost at the same time (since they are similar with the exception of a few functions) and I get an error when I compiler the server in two places where I send a data type sockaddr_in to a function and then try to bind or accept (happens in both functions). Here is my program:

Code:
#include <iostream.h>
#include <sys/types.h>
#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <string.h>
#include <unistd.h>
#include <fstream.h>
#include <sys/param.h>
#include <stdlib.h>

#define PACKETSIZE 20
#define PORTNUM 39992

typedef enum {data, ack} servicetype;

typedef struct
{
	servicetype service;
	int sequence;
	int datasize;
	int last;
	char data[PACKETSIZE];
	int checksum;
} PACKET;

struct sockaddr_in getHost()
{
	struct sockaddr_in sa;
	struct hostent * ph;
	char myname[MAXHOSTNAMELEN + 1];
	
	gethostname(myname, MAXHOSTNAMELEN);
	
	if((ph = gethostbyname(myname)) == NULL)
	{
		cout << "gethosbyname has failed! Exiting..." << endl;
		exit(1);
	}
	
	memset(&sa, 0, sizeof(struct sockaddr_in));
	
	sa.sin_family = ph->h_addrtype;
	sa.sin_port = htons(PORTNUM);
	
	return sa;
}

int openSocket()
{
	int sock;
	
	if((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0)
	{
		cout << "Error getting socket! Exiting..." << endl;
		exit(1);
	}
	
	return sock;
	
}

void bindAndListen(int sock, struct sockaddr_in sa)
{
	if(bind(sock, &sa, sizeof(sa)) < 0)  //Happens Here
	{
		cout << "Bind failed! Exiting..." << endl;
		exit(1);
	}
	listen(sock, 5);
}

int acceptConnection(int sock)
{
	int sd;
	struct sockaddr_in sa;
	unsigned int saSize;
	
	saSize = sizeof(sa);
	 
	if((sd = accept(sock, &sa, &saSize)) < 0)  //Add here!!
	{
		cout << "Accept failed! Exiting..." << endl;
		exit(1);
	}
	
	cout << "Connection established with: " << sa.sin_addr.s_addr << endl;
	
	return sd;
}

void getFile(FILE * file, int sock)
{
	PACKET * packet;
	int x;
	
	packet = (PACKET *) malloc (sizeof(*packet));
	
	do
	{
		if(recv(sock, packet, sizeof(*packet), 0) <= 0)
		{
			cout << "Error receiving file! Exiting..." << endl;
			exit(1);
		}
		cout << "Recieved Packet: " << packet->sequence << " " << packet->data << endl;
		
		for(x = 0; x < packet->datasize; x++)
			putc(packet->data[x], file);
			
		//if(packet->sequence % 5 == 4)
		// ACK
		
	} while(!packet->last);
	
	fclose(file);
}


typedef unsigned int Uint; //non negative int
typedef unsigned char Uchar;

//CRC table found online
Uint crc_table[] =
{
	0x0000, 0xC0C1, 0xC181, 0x0140, 0xC301, 0x03C0, 0x0280, 0xC241,
	0xC601, 0x06C0, 0x0780, 0xC741, 0x0500, 0xC5C1, 0xC481, 0x0440,
	0xCC01, 0x0CC0, 0x0D80, 0xCD41, 0x0F00, 0xCFC1, 0xCE81, 0x0E40,
	0x0A00, 0xCAC1, 0xCB81, 0x0B40, 0xC901, 0x09C0, 0x0880, 0xC841,
	0xD801, 0x18C0, 0x1980, 0xD941, 0x1B00, 0xDBC1, 0xDA81, 0x1A40,
	0x1E00, 0xDEC1, 0xDF81, 0x1F40, 0xDD01, 0x1DC0, 0x1C80, 0xDC41,
	0x1400, 0xD4C1, 0xD581, 0x1540, 0xD701, 0x17C0, 0x1680, 0xD641,
	0xD201, 0x12C0, 0x1380, 0xD341, 0x1100, 0xD1C1, 0xD081, 0x1040,
	0xF001, 0x30C0, 0x3180, 0xF141, 0x3300, 0xF3C1, 0xF281, 0x3240,
	0x3600, 0xF6C1, 0xF781, 0x3740, 0xF501, 0x35C0, 0x3480, 0xF441,
	0x3C00, 0xFCC1, 0xFD81, 0x3D40, 0xFF01, 0x3FC0, 0x3E80, 0xFE41,
	0xFA01, 0x3AC0, 0x3B80, 0xFB41, 0x3900, 0xF9C1, 0xF881, 0x3840,
	0x2800, 0xE8C1, 0xE981, 0x2940, 0xEB01, 0x2BC0, 0x2A80, 0xEA41,
	0xEE01, 0x2EC0, 0x2F80, 0xEF41, 0x2D00, 0xEDC1, 0xEC81, 0x2C40,
	0xE401, 0x24C0, 0x2580, 0xE541, 0x2700, 0xE7C1, 0xE681, 0x2640,
	0x2200, 0xE2C1, 0xE381, 0x2340, 0xE101, 0x21C0, 0x2080, 0xE041,
	0xA001, 0x60C0, 0x6180, 0xA141, 0x6300, 0xA3C1, 0xA281, 0x6240,
	0x6600, 0xA6C1, 0xA781, 0x6740, 0xA501, 0x65C0, 0x6480, 0xA441,
	0x6C00, 0xACC1, 0xAD81, 0x6D40, 0xAF01, 0x6FC0, 0x6E80, 0xAE41,
	0xAA01, 0x6AC0, 0x6B80, 0xAB41, 0x6900, 0xA9C1, 0xA881, 0x6840,
	0x7800, 0xB8C1, 0xB981, 0x7940, 0xBB01, 0x7BC0, 0x7A80, 0xBA41,
	0xBE01, 0x7EC0, 0x7F80, 0xBF41, 0x7D00, 0xBDC1, 0xBC81, 0x7C40,
	0xB401, 0x74C0, 0x7580, 0xB541, 0x7700, 0xB7C1, 0xB681, 0x7640,
	0x7200, 0xB2C1, 0xB381, 0x7340, 0xB101, 0x71C0, 0x7080, 0xB041,
	0x5000, 0x90C1, 0x9181, 0x5140, 0x9301, 0x53C0, 0x5280, 0x9241,
	0x9601, 0x56C0, 0x5780, 0x9741, 0x5500, 0x95C1, 0x9481, 0x5440,
	0x9C01, 0x5CC0, 0x5D80, 0x9D41, 0x5F00, 0x9FC1, 0x9E81, 0x5E40,
	0x5A00, 0x9AC1, 0x9B81, 0x5B40, 0x9901, 0x59C0, 0x5880, 0x9841,
	0x8801, 0x48C0, 0x4980, 0x8941, 0x4B00, 0x8BC1, 0x8A81, 0x4A40,
	0x4E00, 0x8EC1, 0x8F81, 0x4F40, 0x8D01, 0x4DC0, 0x4C80, 0x8C41,
	0x4400, 0x84C1, 0x8581, 0x4540, 0x8701, 0x47C0, 0x4680, 0x8641,
	0x8201, 0x42C0, 0x4380, 0x8341, 0x4100, 0x81C1, 0x8081, 0x4040,
};

int main (int argc, char * const argv[])
{
	int sock, sockfd;
	struct sockaddr_in myAddr;
	FILE * file;
	int ch; 
	long crcIn = 0;
	Uint acc0 = 0xFFFF;
	
	myAddr = getHost();
	sock = openSocket();
	bindAndListen(sock, myAddr);
	
	sockfd = acceptConnection(sock);
	
	getFile(file, sock);
	
	//CRC stuff here
	//need to recieve CRC
	while((ch = getc(file)) != EOF)
	{
		acc0 = crc_table[(Uchar) ch ^ (Uchar) acc0] ^ (Uchar) (acc0 >> 8); //calculate CRC
	}
	
	cout << "CRC checksum is: " << std::hex << acc0 << "." << endl; //Print CRC
	
	cout << "Checking CRC for equality..." << endl;
		
	if (crcIn == (int)acc0)
		cout << "CRC check validated!" << endl;
	else if (crcIn != (int)acc0)
		cout << "CRC check Failed!" << endl;
	
	return 0;
}
here are the errors I recieve:

server.cpp: In function `void bindAndListen(int, sockaddr_in)':
server.cpp:66: type `const sockaddr' is not a base type for type `sockaddr_in'
server.cpp: In function `int acceptConnection(int)':
server.cpp:82: type `sockaddr' is not a base type for type `sockaddr_in'

Any help or explanation as to why this is happening would be awesome. I'm new to client/server programs but I'm trying Thanks!!

-AquamaN
 
Old 05-01-2004, 07:25 PM   #2
ToniT
Senior Member
 
Registered: Oct 2003
Location: Zurich, Switzerland
Distribution: Debian/unstable
Posts: 1,357

Rep: Reputation: 47
According to the man page (accept(2)), the struct is named as 'sockaddr', not 'sockaddr_in'.
 
Old 05-01-2004, 08:00 PM   #3
rkef
Member
 
Registered: Mar 2004
Location: bursa
Posts: 110

Rep: Reputation: 15
ToniT is right; you should be casting your sockaddr_in's to sockaddr's (that's just how it's done I believe; ie. bind and some other such functions take a struct sockaddr ).
 
Old 05-02-2004, 08:28 AM   #4
chris78
LQ Newbie
 
Registered: Mar 2004
Location: germany
Distribution: Slackware & RedHat
Posts: 28

Rep: Reputation: 15
Exactly correct.
And casting is a legal way here because all sockaddr_xxx structs are of identical size.

This is from sys/socket.h and shows the point where all the types go into one union.
Code:
/* This is the type we use for generic socket address arguments.

   With GCC 2.7 and later, the funky union causes redeclarations or
   uses with any of the listed types to be allowed without complaint.
   G++ 2.7 does not support transparent unions so there we want the
   old-style declaration, too.  */
#if defined __cplusplus || !__GNUC_PREREQ (2, 7) || !defined __USE_GNU
# define __SOCKADDR_ARG		struct sockaddr *__restrict
# define __CONST_SOCKADDR_ARG	__const struct sockaddr *
#else
/* Add more `struct sockaddr_AF' types here as necessary.
   These are all the ones I found on NetBSD and Linux.  */
# define __SOCKADDR_ALLTYPES \
  __SOCKADDR_ONETYPE (sockaddr) \
  __SOCKADDR_ONETYPE (sockaddr_at) \
  __SOCKADDR_ONETYPE (sockaddr_ax25) \
  __SOCKADDR_ONETYPE (sockaddr_dl) \
  __SOCKADDR_ONETYPE (sockaddr_eon) \
  __SOCKADDR_ONETYPE (sockaddr_in) \
  __SOCKADDR_ONETYPE (sockaddr_in6) \
  __SOCKADDR_ONETYPE (sockaddr_inarp) \
  __SOCKADDR_ONETYPE (sockaddr_ipx) \
  __SOCKADDR_ONETYPE (sockaddr_iso) \
  __SOCKADDR_ONETYPE (sockaddr_ns) \
  __SOCKADDR_ONETYPE (sockaddr_un) \
  __SOCKADDR_ONETYPE (sockaddr_x25)

# define __SOCKADDR_ONETYPE(type) struct type *__restrict __##type##__;
typedef union { __SOCKADDR_ALLTYPES
	      } __SOCKADDR_ARG __attribute__ ((__transparent_union__));
# undef __SOCKADDR_ONETYPE
# define __SOCKADDR_ONETYPE(type) __const struct type *__restrict __##type##__;
typedef union { __SOCKADDR_ALLTYPES
	      } __CONST_SOCKADDR_ARG __attribute__ ((__transparent_union__));
# undef __SOCKADDR_ONETYPE
#endif

Chris
 
Old 05-02-2004, 03:52 PM   #5
AquamaN
Member
 
Registered: Oct 2002
Location: Ohio, USA
Distribution: OS X 10.4.8, Ubuntu 6.10
Posts: 146

Original Poster
Rep: Reputation: 15
got it working. thanks a lot you guys! as always, you rock! :-)
 
  


Reply


Thread Tools Search this Thread
Search this Thread:

Advanced Search

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 Off
HTML code is Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
about struct sockaddr_in greghua Programming 11 07-29-2005 11:01 AM
Accessing member functions of sockaddr_in Stack Overflow Programming 4 01-27-2005 05:11 PM
inet_ntoa() problem with array of sockaddr_in ahogg Programming 5 05-05-2004 11:21 AM


All times are GMT -5. The time now is 01:33 AM.

Main Menu
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
identi.ca: @linuxquestions
Facebook: linuxquestions Google+: linuxquestions
Open Source Consulting | Domain Registration