HEEELLLPPP socket programing instant messaging

S

Sean

Hi Everyone,
My apologies for a somewhat dump question but I am really stuck. I have
been working on this code for two days straight I am dont know what is
wrong with it. when I run the code, All I get is Input: and the program
quits. I also tried reading this online but I didn't quite get it.

What is the diff between sin_addr and sin_addr.s_addr. My understanding
is that the latter is the IP address of my machine where as the former
is the destination IP address.

Also why doesn't the program stop at
cout << "Input: ";
cin.get(buf, MAX_LINE, '\n');

for the user to enter something.

I am trying to write an instant messaging program (peer to peer).

Below is my code.

Thanks in advance


#include <netdb.h>
#include <netinet/in.h>
#include <unistd.h>
#include <iostream>
#include <arpa/inet.h>

#define MAX_LINE 100
#define LINE_ARRAY_SIZE (MAX_LINE+1)
#define PORT 15002

using namespace std;

int main()
{
int socketDescriptor;
struct sockaddr_in serverAddress;
char buf[LINE_ARRAY_SIZE], c;
struct hostent *hostInfo;

cout << "Enter IP address: ";
cin.get(buf, MAX_LINE, '\n');

socketDescriptor = socket(AF_INET, SOCK_STREAM, 0);
if (socketDescriptor < 0) {
cerr << "cannot create socket\n";
exit(1);
}

hostInfo = gethostbyname(buf);
if (hostInfo == NULL) {
cout << "problem interpreting host: " << buf << "\n";
exit(1);
}

memset(&serverAddress, 0, sizeof(serverAddress));
serverAddress.sin_family = AF_INET;
serverAddress.sin_port = htons(PORT);
inet_aton(buf, &(serverAddress.sin_addr));
serverAddress.sin_addr.s_addr = htonl(INADDR_ANY);
if( bind(socketDescriptor, (struct sockaddr *) &serverAddress,
sizeof(serverAddress)) )
cerr << "bind() failed" ;

memset(buf, 0x0, LINE_ARRAY_SIZE);
cout << "Input: ";
cin.get(buf, MAX_LINE, '\n');
while (cin.get(c) && c != '\n')
;


// Send the line to the server.
if (send(socketDescriptor, buf, strlen(buf) + 1, 0) < 0) {
cerr << "cannot send data ";
close(socketDescriptor);
exit(1);
}

// Zero out the buffer.
memset(buf, 0x0, LINE_ARRAY_SIZE);

// Read the modified line back from the server.
if (recv(socketDescriptor, buf, MAX_LINE, 0) < 0) {
cerr << "didn't get response from server?";
close(socketDescriptor);
exit(1);
}

close(socketDescriptor);
return 0;
}
 
A

Alan Johnson

Sean said:
Hi Everyone,
My apologies for a somewhat dump question but I am really stuck. I have
been working on this code for two days straight I am dont know what is
wrong with it. when I run the code, All I get is Input: and the program
quits. I also tried reading this online but I didn't quite get it.

What is the diff between sin_addr and sin_addr.s_addr. My understanding
is that the latter is the IP address of my machine where as the former
is the destination IP address.

Also why doesn't the program stop at
cout << "Input: ";
cin.get(buf, MAX_LINE, '\n');

for the user to enter something.

I am trying to write an instant messaging program (peer to peer).

Below is my code.

Thanks in advance

[irrelevant code removed]
cout << "Enter IP address: ";
cin.get(buf, MAX_LINE, '\n');
cout << "Input: ";
cin.get(buf, MAX_LINE, '\n');

The get() method does not remove the delimiter from the stream. So,
let's say you type "192.168.1.1\n" when prompted for the IP address.
The "192.168.1.1" is removed from the stream, but "\n" is left in there.
Now, when you do the second get(), it immediately encounters your
delimiter and returns a zero length string.

Instead of using get(), use getline(). As in:
cin.getline(buf, MAX_LINE) ;

Or better yet, skip the whole MAX_LINE nonsense, and use std::string.

#include <string>
// ...
std::string ip_address;
std::getline(std::cin, ip_address);

Use the c_str() method when you need to access it as a c-style string.
 
B

bjeremy

Sean said:
Hi Everyone,
My apologies for a somewhat dump question but I am really stuck. I have
been working on this code for two days straight I am dont know what is
wrong with it. when I run the code, All I get is Input: and the program
quits. I also tried reading this online but I didn't quite get it.

What is the diff between sin_addr and sin_addr.s_addr. My understanding
is that the latter is the IP address of my machine where as the former
is the destination IP address.

Also why doesn't the program stop at
cout << "Input: ";
cin.get(buf, MAX_LINE, '\n');

for the user to enter something.

I am trying to write an instant messaging program (peer to peer).

Below is my code.

Thanks in advance


#include <netdb.h>
#include <netinet/in.h>
#include <unistd.h>
#include <iostream>
#include <arpa/inet.h>

#define MAX_LINE 100
#define LINE_ARRAY_SIZE (MAX_LINE+1)
#define PORT 15002

using namespace std;

int main()
{
int socketDescriptor;
struct sockaddr_in serverAddress;
char buf[LINE_ARRAY_SIZE], c;
struct hostent *hostInfo;

cout << "Enter IP address: ";
cin.get(buf, MAX_LINE, '\n');

socketDescriptor = socket(AF_INET, SOCK_STREAM, 0);
if (socketDescriptor < 0) {
cerr << "cannot create socket\n";
exit(1);
}

hostInfo = gethostbyname(buf);
if (hostInfo == NULL) {
cout << "problem interpreting host: " << buf << "\n";
exit(1);
}

memset(&serverAddress, 0, sizeof(serverAddress));
serverAddress.sin_family = AF_INET;
serverAddress.sin_port = htons(PORT);
inet_aton(buf, &(serverAddress.sin_addr));
serverAddress.sin_addr.s_addr = htonl(INADDR_ANY);
if( bind(socketDescriptor, (struct sockaddr *) &serverAddress,
sizeof(serverAddress)) )
cerr << "bind() failed" ;

memset(buf, 0x0, LINE_ARRAY_SIZE);
cout << "Input: ";
cin.get(buf, MAX_LINE, '\n');
while (cin.get(c) && c != '\n')
;


// Send the line to the server.
if (send(socketDescriptor, buf, strlen(buf) + 1, 0) < 0) {
cerr << "cannot send data ";
close(socketDescriptor);
exit(1);
}

// Zero out the buffer.
memset(buf, 0x0, LINE_ARRAY_SIZE);

// Read the modified line back from the server.
if (recv(socketDescriptor, buf, MAX_LINE, 0) < 0) {
cerr << "didn't get response from server?";
close(socketDescriptor);
exit(1);
}

close(socketDescriptor);
return 0;
}

For your other question as to why your program doesn't stop at Input:.
The answer is that you previously issued a :
cout << "Enter IP address: ";
cin.get(buf, MAX_LINE, '\n');
but never cleared the "buf"... so there is still a line in your buffer
and it is exiting out... However, after you fix this (a few ways of
doing it, I'll leave it up to you to pick one), you will still have
some problems... so for you next question the difference between
sin_addr and s_addr can be confusing... but sin_addr is a member of the
struct sockaddr_in (internet socket address struct look in
netinet/in.h)... the member is of type in_addr. Struct in_addr has only
one member and that is s_addr... s_addr is a 32 bit IPv4 Address
supposedly in network byte order (big endian). This IP address can be
any IP Address and is not related to a local host or destination
address per se.

In your example I really can't tell if you are trying to open a client
socket or a server socket... Let's say you are trying to set up a
server socket, you bind to your local default IP Address, but after a
bind you should issue a listen() and then an accept() to await incoming
connections (if you use blocking i/o, which it looks like you do this
call will block).. Once you accept a client connection, then you could
send/recv data off that connection. But you will use the socket
descriptor of the new connection, not the descriptor you receved by
establishing your server socket

// Create socket for listening for client connection requests.
listenSocket = socket(AF_INET, SOCK_STREAM, 0);
if (listenSocket < 0) {
cerr << "cannot create listen socket";
exit(1);
}

// Bind listen socket to listen port. First set various fields in
// the serverAddress structure, then call bind().
serverAddress.sin_family = AF_INET;
serverAddress.sin_addr.s_addr = htonl(INADDR_ANY);
serverAddress.sin_port = htons(listenPort);

if (bind(listenSocket,
(struct sockaddr *) &serverAddress,
sizeof(serverAddress)) < 0) {
cerr << "cannot bind socket";
exit(1);
}

// Wait for connections from clients.
listen(listenSocket, 5);

while (1) {
cout << "Waiting for TCP connection on port " << listenPort << "
....\n";

// Accept a connection with a client that is requesting one.
clientAddressLength = sizeof(clientAddress);
connectSocket = accept(listenSocket,
(struct sockaddr *) &clientAddress,
&clientAddressLength);
if (connectSocket < 0) {
cerr << "cannot accept connection ";
exit(1);
}

//Read from the socket or whatever
while (recv(connectSocket, line, MAXMSG, 0) > 0) {
cout << line << "\n";
}

A client socket is somewhat different.. but there should be lots of
examples on the web on this...
 
S

Sean

Thanks for the rely. I am actually trying to make a program that is
both a client and a server. This means, that if you and I are both
running this code on our machines, I can make a call to you, in which
case, you will be the server and I will be the client and you can make
a call to me.

Sean said:
Hi Everyone,
My apologies for a somewhat dump question but I am really stuck. I have
been working on this code for two days straight I am dont know what is
wrong with it. when I run the code, All I get is Input: and the program
quits. I also tried reading this online but I didn't quite get it.

What is the diff between sin_addr and sin_addr.s_addr. My understanding
is that the latter is the IP address of my machine where as the former
is the destination IP address.

Also why doesn't the program stop at
cout << "Input: ";
cin.get(buf, MAX_LINE, '\n');

for the user to enter something.

I am trying to write an instant messaging program (peer to peer).

Below is my code.

Thanks in advance


#include <netdb.h>
#include <netinet/in.h>
#include <unistd.h>
#include <iostream>
#include <arpa/inet.h>

#define MAX_LINE 100
#define LINE_ARRAY_SIZE (MAX_LINE+1)
#define PORT 15002

using namespace std;

int main()
{
int socketDescriptor;
struct sockaddr_in serverAddress;
char buf[LINE_ARRAY_SIZE], c;
struct hostent *hostInfo;

cout << "Enter IP address: ";
cin.get(buf, MAX_LINE, '\n');

socketDescriptor = socket(AF_INET, SOCK_STREAM, 0);
if (socketDescriptor < 0) {
cerr << "cannot create socket\n";
exit(1);
}

hostInfo = gethostbyname(buf);
if (hostInfo == NULL) {
cout << "problem interpreting host: " << buf << "\n";
exit(1);
}

memset(&serverAddress, 0, sizeof(serverAddress));
serverAddress.sin_family = AF_INET;
serverAddress.sin_port = htons(PORT);
inet_aton(buf, &(serverAddress.sin_addr));
serverAddress.sin_addr.s_addr = htonl(INADDR_ANY);
if( bind(socketDescriptor, (struct sockaddr *) &serverAddress,
sizeof(serverAddress)) )
cerr << "bind() failed" ;

memset(buf, 0x0, LINE_ARRAY_SIZE);
cout << "Input: ";
cin.get(buf, MAX_LINE, '\n');
while (cin.get(c) && c != '\n')
;


// Send the line to the server.
if (send(socketDescriptor, buf, strlen(buf) + 1, 0) < 0) {
cerr << "cannot send data ";
close(socketDescriptor);
exit(1);
}

// Zero out the buffer.
memset(buf, 0x0, LINE_ARRAY_SIZE);

// Read the modified line back from the server.
if (recv(socketDescriptor, buf, MAX_LINE, 0) < 0) {
cerr << "didn't get response from server?";
close(socketDescriptor);
exit(1);
}

close(socketDescriptor);
return 0;
}

For your other question as to why your program doesn't stop at Input:.
The answer is that you previously issued a :
cout << "Enter IP address: ";
cin.get(buf, MAX_LINE, '\n');
but never cleared the "buf"... so there is still a line in your buffer
and it is exiting out... However, after you fix this (a few ways of
doing it, I'll leave it up to you to pick one), you will still have
some problems... so for you next question the difference between
sin_addr and s_addr can be confusing... but sin_addr is a member of the
struct sockaddr_in (internet socket address struct look in
netinet/in.h)... the member is of type in_addr. Struct in_addr has only
one member and that is s_addr... s_addr is a 32 bit IPv4 Address
supposedly in network byte order (big endian). This IP address can be
any IP Address and is not related to a local host or destination
address per se.

In your example I really can't tell if you are trying to open a client
socket or a server socket... Let's say you are trying to set up a
server socket, you bind to your local default IP Address, but after a
bind you should issue a listen() and then an accept() to await incoming
connections (if you use blocking i/o, which it looks like you do this
call will block).. Once you accept a client connection, then you could
send/recv data off that connection. But you will use the socket
descriptor of the new connection, not the descriptor you receved by
establishing your server socket

// Create socket for listening for client connection requests.
listenSocket = socket(AF_INET, SOCK_STREAM, 0);
if (listenSocket < 0) {
cerr << "cannot create listen socket";
exit(1);
}

// Bind listen socket to listen port. First set various fields in
// the serverAddress structure, then call bind().
serverAddress.sin_family = AF_INET;
serverAddress.sin_addr.s_addr = htonl(INADDR_ANY);
serverAddress.sin_port = htons(listenPort);

if (bind(listenSocket,
(struct sockaddr *) &serverAddress,
sizeof(serverAddress)) < 0) {
cerr << "cannot bind socket";
exit(1);
}

// Wait for connections from clients.
listen(listenSocket, 5);

while (1) {
cout << "Waiting for TCP connection on port " << listenPort << "
...\n";

// Accept a connection with a client that is requesting one.
clientAddressLength = sizeof(clientAddress);
connectSocket = accept(listenSocket,
(struct sockaddr *) &clientAddress,
&clientAddressLength);
if (connectSocket < 0) {
cerr << "cannot accept connection ";
exit(1);
}

//Read from the socket or whatever
while (recv(connectSocket, line, MAXMSG, 0) > 0) {
cout << line << "\n";
}

A client socket is somewhat different.. but there should be lots of
examples on the web on this...
 
S

Sean

Thanks for the rely. I am actually trying to make a program that is
both a client and a server. This means, that if you and I are both
running this code on our machines, I can make a call to you, in which
case, you will be the server and I will be the client and you can make
a call to me. So I am not sure if I am going about this the right way
or not.

Sean said:
Hi Everyone,
My apologies for a somewhat dump question but I am really stuck. I have
been working on this code for two days straight I am dont know what is
wrong with it. when I run the code, All I get is Input: and the program
quits. I also tried reading this online but I didn't quite get it.

What is the diff between sin_addr and sin_addr.s_addr. My understanding
is that the latter is the IP address of my machine where as the former
is the destination IP address.

Also why doesn't the program stop at
cout << "Input: ";
cin.get(buf, MAX_LINE, '\n');

for the user to enter something.

I am trying to write an instant messaging program (peer to peer).

Below is my code.

Thanks in advance


#include <netdb.h>
#include <netinet/in.h>
#include <unistd.h>
#include <iostream>
#include <arpa/inet.h>

#define MAX_LINE 100
#define LINE_ARRAY_SIZE (MAX_LINE+1)
#define PORT 15002

using namespace std;

int main()
{
int socketDescriptor;
struct sockaddr_in serverAddress;
char buf[LINE_ARRAY_SIZE], c;
struct hostent *hostInfo;

cout << "Enter IP address: ";
cin.get(buf, MAX_LINE, '\n');

socketDescriptor = socket(AF_INET, SOCK_STREAM, 0);
if (socketDescriptor < 0) {
cerr << "cannot create socket\n";
exit(1);
}

hostInfo = gethostbyname(buf);
if (hostInfo == NULL) {
cout << "problem interpreting host: " << buf << "\n";
exit(1);
}

memset(&serverAddress, 0, sizeof(serverAddress));
serverAddress.sin_family = AF_INET;
serverAddress.sin_port = htons(PORT);
inet_aton(buf, &(serverAddress.sin_addr));
serverAddress.sin_addr.s_addr = htonl(INADDR_ANY);
if( bind(socketDescriptor, (struct sockaddr *) &serverAddress,
sizeof(serverAddress)) )
cerr << "bind() failed" ;

memset(buf, 0x0, LINE_ARRAY_SIZE);
cout << "Input: ";
cin.get(buf, MAX_LINE, '\n');
while (cin.get(c) && c != '\n')
;


// Send the line to the server.
if (send(socketDescriptor, buf, strlen(buf) + 1, 0) < 0) {
cerr << "cannot send data ";
close(socketDescriptor);
exit(1);
}

// Zero out the buffer.
memset(buf, 0x0, LINE_ARRAY_SIZE);

// Read the modified line back from the server.
if (recv(socketDescriptor, buf, MAX_LINE, 0) < 0) {
cerr << "didn't get response from server?";
close(socketDescriptor);
exit(1);
}

close(socketDescriptor);
return 0;
}

For your other question as to why your program doesn't stop at Input:.
The answer is that you previously issued a :
cout << "Enter IP address: ";
cin.get(buf, MAX_LINE, '\n');
but never cleared the "buf"... so there is still a line in your buffer
and it is exiting out... However, after you fix this (a few ways of
doing it, I'll leave it up to you to pick one), you will still have
some problems... so for you next question the difference between
sin_addr and s_addr can be confusing... but sin_addr is a member of the
struct sockaddr_in (internet socket address struct look in
netinet/in.h)... the member is of type in_addr. Struct in_addr has only
one member and that is s_addr... s_addr is a 32 bit IPv4 Address
supposedly in network byte order (big endian). This IP address can be
any IP Address and is not related to a local host or destination
address per se.

In your example I really can't tell if you are trying to open a client
socket or a server socket... Let's say you are trying to set up a
server socket, you bind to your local default IP Address, but after a
bind you should issue a listen() and then an accept() to await incoming
connections (if you use blocking i/o, which it looks like you do this
call will block).. Once you accept a client connection, then you could
send/recv data off that connection. But you will use the socket
descriptor of the new connection, not the descriptor you receved by
establishing your server socket

// Create socket for listening for client connection requests.
listenSocket = socket(AF_INET, SOCK_STREAM, 0);
if (listenSocket < 0) {
cerr << "cannot create listen socket";
exit(1);
}

// Bind listen socket to listen port. First set various fields in
// the serverAddress structure, then call bind().
serverAddress.sin_family = AF_INET;
serverAddress.sin_addr.s_addr = htonl(INADDR_ANY);
serverAddress.sin_port = htons(listenPort);

if (bind(listenSocket,
(struct sockaddr *) &serverAddress,
sizeof(serverAddress)) < 0) {
cerr << "cannot bind socket";
exit(1);
}

// Wait for connections from clients.
listen(listenSocket, 5);

while (1) {
cout << "Waiting for TCP connection on port " << listenPort << "
...\n";

// Accept a connection with a client that is requesting one.
clientAddressLength = sizeof(clientAddress);
connectSocket = accept(listenSocket,
(struct sockaddr *) &clientAddress,
&clientAddressLength);
if (connectSocket < 0) {
cerr << "cannot accept connection ";
exit(1);
}

//Read from the socket or whatever
while (recv(connectSocket, line, MAXMSG, 0) > 0) {
cout << line << "\n";
}

A client socket is somewhat different.. but there should be lots of
examples on the web on this...
 
B

bjeremy

Sean said:
Thanks for the rely. I am actually trying to make a program that is
both a client and a server. This means, that if you and I are both
running this code on our machines, I can make a call to you, in which
case, you will be the server and I will be the client and you can make
a call to me. So I am not sure if I am going about this the right way
or not.

Well if you want to do that you would need to use non-blocking i/o. The
first part of your program would set up a server socket that
listen()-ed to a defined port. The non-blocking i/o would be needed in
order to not wait on the accept(). While you are listening for incoming
connections, you can do other stuff... like open up a client connection
of your own. This is straight forward, but if you are new to socket
programming I suggest you read about non-blocking i/o and
select()/poll().
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,982
Messages
2,570,186
Members
46,743
Latest member
WoodrowMea

Latest Threads

Top