Programming Forums
User Name Password Register
 

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

Reply
 
Thread Tools Display Modes
Old Mar 1st, 2008, 11:14 AM   #1
Soulstorm
Hobbyist Programmer
 
Soulstorm's Avatar
 
Join Date: Jan 2006
Location: Menidi, Athens, Greece
Posts: 234
Rep Power: 3 Soulstorm is on a distinguished road
Simple BSD Sockets Problem

I am diving into network connections, using the BSD sockets. My ultimate goal is to make a very basic IRC client, just to learn how to do network connections. My operating system is OS X, but I don't think that makes a difference, since I believe BSD Sockets exist in other platforms, too.

I am stuck.

I have created a command line tool in C and I have the following code:

c Syntax (Toggle Plain Text)
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <unistd.h>
  4. #include <errno.h>
  5. #include <string.h>
  6. #include <netdb.h>
  7. #include <sys/types.h>
  8. #include <netinet/in.h>
  9. #include <sys/socket.h>
  10.  
  11. #define PORT 6667 // the port client will be connecting to
  12.  
  13. #define MAXDATASIZE 1000 // max number of bytes we can get at once
  14.  
  15. int main(int argc, char *argv[])
  16. {
  17. int sockfd, numbytes;
  18. char buf[MAXDATASIZE];
  19. struct hostent *he;
  20. struct sockaddr_in their_addr; // connector's address information
  21.  
  22. he = gethostbyname("efnet.teleglobe.net");
  23. sockfd = socket(PF_INET, SOCK_STREAM, 0);
  24. if (sockfd < 0) {
  25. printf("error creating the socket\n");
  26. }
  27. their_addr.sin_family = AF_INET;
  28. their_addr.sin_port = htons(PORT);
  29. their_addr.sin_addr = *((struct in_addr *)he->h_addr);
  30. memset(their_addr.sin_zero, '\0', sizeof their_addr.sin_zero);
  31.  
  32.  
  33. if (connect(sockfd, (struct sockaddr *)&their_addr,
  34. sizeof their_addr) == -1) {
  35. perror("connect\n");
  36. exit(1);
  37. }
  38. else
  39. printf("You got the connection to the server!\n");
  40. char p[] = "join #macfilez";
  41. send(sockfd, p, sizeof(p), 0);
  42.  
  43. recv(sockfd, buf, sizeof(buf), 0);
  44. buf[numbytes] = '\0';
  45. printf("Received: %s",buf);
  46. close(sockfd);
  47.  
  48. return 0;
  49. }
The server I put was a server running on IRC's EFNet network. I was supposed to receive a message, from the server, right? Not only this doesn't happen, my program also crashes without showing anything! (the debugger comes up with no explanation).

Any ideas why? Actually, I must have made a newbie mistake due to my ignorance. Please enlighten me.
__________________
Project::Soulstorm (personal homepage)

Last edited by Soulstorm; Mar 1st, 2008 at 11:27 AM.
Soulstorm is offline   Reply With Quote
Old Mar 1st, 2008, 7:51 PM   #2
Game_Ender
Professional Programmer
 
Game_Ender's Avatar
 
Join Date: May 2006
Location: Maryland, USA
Posts: 306
Rep Power: 3 Game_Ender is on a distinguished road
Re: Simple BSD Sockets Problem

Where is your server code?

Well you aren't check the return of "gethostbyname" which could very well be NULL. That would be a quick crash. You also don't zero out you sockaddr_in structure before using it. Here is some code I have that does a similar thing:
cpp Syntax (Toggle Plain Text)
  1. memset(&m_addr, 0, sizeof(m_addr));
  2. m_addr.sin_family = AF_INET; // host byte order
  3. m_addr.sin_port = htons(port); // short, network byte order
  4. m_addr.sin_addr = *((struct in_addr *)he->h_addr);

I think you are trying to do something simular with this:
cpp Syntax (Toggle Plain Text)
  1. memset(their_addr.sin_zero, '\0', sizeof their_addr.sin_zero);

Wikipedia has good article here.
__________________
Robotics @ Maryland AUV Team - Software Lead
Game_Ender is offline   Reply With Quote
Old Mar 2nd, 2008, 10:34 AM   #3
Soulstorm
Hobbyist Programmer
 
Soulstorm's Avatar
 
Join Date: Jan 2006
Location: Menidi, Athens, Greece
Posts: 234
Rep Power: 3 Soulstorm is on a distinguished road
Re: Simple BSD Sockets Problem

Quote:
Originally Posted by Game_Ender View Post
Where is your server code?

Well you aren't check the return of "gethostbyname" which could very well be NULL. That would be a quick crash. You also don't zero out you sockaddr_in structure before using it. Here is some code I have that does a similar thing:
cpp Syntax (Toggle Plain Text)
  1. memset(&m_addr, 0, sizeof(m_addr));
  2. m_addr.sin_family = AF_INET; // host byte order
  3. m_addr.sin_port = htons(port); // short, network byte order
  4. m_addr.sin_addr = *((struct in_addr *)he->h_addr);

I think you are trying to do something simular with this:
cpp Syntax (Toggle Plain Text)
  1. memset(their_addr.sin_zero, '\0', sizeof their_addr.sin_zero);

Wikipedia has good article here.

Thanks for the reply. There is no server code. The host I connect to is an IRC network host.
__________________
Project::Soulstorm (personal homepage)
Soulstorm is offline   Reply With Quote
Old Mar 2nd, 2008, 4:07 PM   #4
The Dark
Expert Programmer
 
Join Date: Jun 2005
Posts: 816
Rep Power: 4 The Dark is on a distinguished road
Re: Simple BSD Sockets Problem

You don't set numBytes to a value before using it. This code:
buf[numbytes] = '\0';
could then try to write to anywhere.
The Dark is offline   Reply With Quote
Old Mar 2nd, 2008, 4:34 PM   #5
Dameon
Troll
 
Dameon's Avatar
 
Join Date: Apr 2005
Location: Texas
Posts: 732
Rep Power: 4 Dameon is on a distinguished road
Re: Simple BSD Sockets Problem

recv will return -1 on error, 0 upon disconnection, or otherwise the number of bytes read. You should probably use that for numbytes. This is from 'man recv'

So make sure to properly handle the return value.

I've only skimmed so that is likely not the only issue.
__________________
MD5(sig) = bcef75433db02e9ad9bf81d6f7c5c270
Dameon is offline   Reply With Quote
Old Mar 3rd, 2008, 7:16 AM   #6
Game_Ender
Professional Programmer
 
Game_Ender's Avatar
 
Join Date: May 2006
Location: Maryland, USA
Posts: 306
Rep Power: 3 Game_Ender is on a distinguished road
Re: Simple BSD Sockets Problem

Yes you should be checking the return of *every* socket call. I usually use wrapper function which do it for me.

I found the IRC spec and I am not sure you are following it correctly. I think you need both "CR" and "LF" which would mean messages end in "\r\n". See more here.

You should also be able to telnet into the server and test out the commands manually if you wish.
__________________
Robotics @ Maryland AUV Team - Software Lead
Game_Ender is offline   Reply With Quote
Old Mar 3rd, 2008, 8:34 AM   #7
Soulstorm
Hobbyist Programmer
 
Soulstorm's Avatar
 
Join Date: Jan 2006
Location: Menidi, Athens, Greece
Posts: 234
Rep Power: 3 Soulstorm is on a distinguished road
Re: Simple BSD Sockets Problem

Actually, this code
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <netdb.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>

#define PORT 6667 // the port client will be connecting to 

#define MAXDATASIZE 2000 // max number of bytes we can get at once 

int main(int argc, char *argv[])
{
    int sockfd, numbytes;
    char buf[MAXDATASIZE];
    struct hostent *he;
    struct sockaddr_in their_addr; // connector's address information
	
    he = gethostbyname("efnet.teleglobe.net");
    sockfd = socket(PF_INET, SOCK_STREAM, 0);
    if (sockfd < 0) {
		printf("error creating the socket\n");
    }
    their_addr.sin_family       = AF_INET;
    their_addr.sin_port         = htons(PORT);
    their_addr.sin_addr         = *((struct in_addr *)he->h_addr);
    memset(their_addr.sin_zero, '\0', sizeof their_addr.sin_zero);
	
	
    if (connect(sockfd, (struct sockaddr *)&their_addr,
				sizeof their_addr) == -1) {
		perror("connect\n");
		exit(1);
    } else {
		printf("You got the connection to the server!\n");

		fprintf(stderr,"After send, entering recv loop\n");
		numbytes=0;
		while(numbytes == 0) {
			fprintf(stderr,"In recv loop\n");
			numbytes=recv(sockfd, buf, sizeof(buf)-1, 0); //-1 b/c you will null terminate
		}
		fprintf(stderr,"After recv loop, %d bytes read.\n",numbytes);
		buf[numbytes] = '\0';
		fprintf(stderr,"After null term, %d bytes read.\n",numbytes);
		printf("Received: %s",buf);
		fflush(stdout);
		close(sockfd);
	}
	return 0;
}
makes my computer connect to the server, and then receives a message saying "NOTICE AUTH ** Processing connection to efnet.teleglobe.net"

That's all. However, I believe I was supposed to see more than this. Perhaps it's the problem that Game_Ended noticed about line endings.
__________________
Project::Soulstorm (personal homepage)
Soulstorm is offline   Reply With Quote
Old Mar 3rd, 2008, 2:50 PM   #8
Soulstorm
Hobbyist Programmer
 
Soulstorm's Avatar
 
Join Date: Jan 2006
Location: Menidi, Athens, Greece
Posts: 234
Rep Power: 3 Soulstorm is on a distinguished road
Re: Simple BSD Sockets Problem

OK, I may need some explanation on sockets.

As far as I understand the general approach is:
  1. Specify a host
  2. connect to the host using connect()
  3. give a command
  4. and then, accept the responce from the server for this command using the recv function

However, I read upon telnet (wikipedia), but I don't quite understand what it is. And I really don't understand what game_ender said about CR and LF. I'm sorry if my questions sound newbish, but I haven't been involved with communication protocols or any kind of networking with programming and I need some basic questions answered...
__________________
Project::Soulstorm (personal homepage)
Soulstorm is offline   Reply With Quote
Old Mar 3rd, 2008, 8:59 PM   #9
Game_Ender
Professional Programmer
 
Game_Ender's Avatar
 
Join Date: May 2006
Location: Maryland, USA
Posts: 306
Rep Power: 3 Game_Ender is on a distinguished road
Re: Simple BSD Sockets Problem

From what I understand telnet is a program that lets you connect to another server on a given port, and then send and receive plan text over a TCP connection. Since the IRC protocol is plain text you can talk to a server "by hand".

Now the issue is that TCP is a stream oriented protcol (its just like reading from a file), you have no idea how many bytes someone has sent you. So you have to build something into your communications protocol to be able tell when messages start in end. In the IRC protocol they want you to put "\r\n" at the end of every message. That is how the server knows you are done sending. Here is an example:
c Syntax (Toggle Plain Text)
  1. /* Bad */
  2. char p[] = "join #macfilez";
  3. /* Good */
  4. char p[] = "join #macfilez\r\n";
__________________
Robotics @ Maryland AUV Team - Software Lead
Game_Ender is offline   Reply With Quote
Old Mar 3rd, 2008, 9:00 PM   #10
Game_Ender
Professional Programmer
 
Game_Ender's Avatar
 
Join Date: May 2006
Location: Maryland, USA
Posts: 306
Rep Power: 3 Game_Ender is on a distinguished road
Re: Simple BSD Sockets Problem

You should really make a dumb server which just prints whatever it is sent so that you at least know what are you sending is correct.
__________________
Robotics @ Maryland AUV Team - Software Lead
Game_Ender 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

Similar Threads
Thread Thread Starter Forum Replies Last Post
Simple blackjack script problem. Need help. jokr004 C++ 6 Feb 10th, 2006 11:44 AM
EXTREMELY simple problem d_heyzie C++ 15 Feb 2nd, 2006 11:32 PM
sockets, problem with select() Wizard1988 C++ 0 Jan 15th, 2006 4:09 PM
Simple Perl / MySQL Problem.. pls help! domquemo Perl 0 Jan 11th, 2006 4:08 AM
repaint() problem in very simple program dotred Java 1 Mar 17th, 2005 5:17 AM




DaniWeb IT Discussion Community
All times are GMT -5. The time now is 9:51 PM.

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