// JP opened flex table

Click to See Complete Forum and Search --> : Socket Troubleshooting


Juntalis
June 9th, 2008, 04:37 PM
Hello, first poster here.

Note that this is a console program I'm working on for an online game to make the administrator's jobs easier. For the moment, it's only Linux compatible, but after I get the concepts of consoles down, and actually finish this, I'll port it to Windows and Mac, too.

Please let me begin by apologizing if I'm going about this all wrong. I'm fairly new to C++, and even newer to any type of Unix system. I originally started in Windows and in Visual Basic, so.. Yeah..

Now first, the source:


#include <netdb.h>
#include <netinet/in.h>
#include <unistd.h>
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define MAX_LINE 100
#define LINE_ARRAY_SIZE (MAX_LINE+1)
int Instr(int start, char *string1, char *string2);
char *Left(char *str, int length);
using namespace std;

int main()
{
int atest = 0;
int socketDescriptor;
unsigned short int serverPort;
struct sockaddr_in serverAddress;
struct hostent *hostInfo;
char buf[LINE_ARRAY_SIZE], c;
char sendbuf[300];

cout << "Enter server host name or IP address: ";
strcpy(buf, "66.230.225.210");

// gethostbyname() takes a host name or ip address in "numbers and
// dots" notation, and returns a pointer to a hostent structure,
// which we'll need later. It's not important for us what this
// structure is actually composed of.
hostInfo = gethostbyname(buf);
if (hostInfo == NULL) {
cout << "problem interpreting host: " << buf << "\n";
exit(1);
}

cout << "Enter server port number: ";
serverPort = 20180;
cin.get(c); // dispose of the newline

// Create a socket. "AF_INET" means it will use the IPv4 protocol.
// "SOCK_STREAM" means it will be a reliable connection (i.e., TCP;
// for UDP use SOCK_DGRAM), and I'm not sure what the 0 for the last
// parameter means, but it seems to work.
socketDescriptor = socket(AF_INET, SOCK_STREAM, 0);
if (socketDescriptor < 0) {
cerr << "cannot create socket\n";
exit(1);
}

// Connect to server. First we have to set some fields in the
// serverAddress structure. The system will assign me an arbitrary
// local port that is not in use.
serverAddress.sin_family = hostInfo->h_addrtype;
memcpy((char *) &serverAddress.sin_addr.s_addr,
hostInfo->h_addr_list[0], hostInfo->h_length);
serverAddress.sin_port = htons(serverPort);

if (connect(socketDescriptor,
(struct sockaddr *) &serverAddress,
sizeof(serverAddress)) < 0) {
cerr << "cannot connect\n";
exit(1);
}


while (!atest) {
// Read the line back from the server.
if (recv(socketDescriptor, buf, MAX_LINE, 0) < 0) {
cerr << "didn't get response from server?";
close(socketDescriptor);
exit(1);
}
if(Instr(0,buf,"DESC") > 0 )
{
strcpy(sendbuf, "NICK Juntalis\nmlogin Juntalis ****\nPING\nstatus\n");
send(socketDescriptor, sendbuf, strlen(sendbuf) + 1, 0);
}
cout << buf;
memset(buf, 0x0, LINE_ARRAY_SIZE);
}

close(socketDescriptor);
return 0;
}

int Instr(int start, char *string1, char *string2)


{
int len=strlen(string1);
int lensub=strlen(string2);
char *substr;
substr = (char*)malloc(lensub);
for(int q=start; q<=len;q++)


{
if(string1[q] == string2[0])


{
for(int t=0; t<lensub;t++)


{
substr[t] = string1[q+t];
}
substr = Left(substr, lensub);
if(!strcmp(substr, string2))


{
return q;
break;
}
}
}
return 0;
}
char *Left(char *str, int length)


{
char *f;

f = (char*)malloc(length);
if (f==NULL) printf("Error allocating memory\n");
strncpy(f,str, length);
f[length] = '\0';

return f;
}


Now I realize that I'm sticking it in an infinite loop, but I'm comfortable with that at the moment, due to the fact that this is a simple test so that I can understand how sockets are dealt with in C++.. Now, the program runs just as I hoped, except one problem. Here's what I get from the console:

[charlie@localhost src]$ ./my_socket_test
Enter server host name or IP address: Enter server port number:
TORIBASH 30
ID 111615
CLIENTS 2;[GameOne]Kimmekim Maveric tirititran TatWaffe Darkvadder Shiv proph3t91 Letterbomb Re2ry Bias PaiCho ThaWolffriden DarianX [GameOne]cyp
NEWGAME 1;1000 70 15 0 0 3 80 1 1 classic 0 0 100 0 0 0 1 0 2 0 0 0 0 0 0 0.000000 0.000000 -9.820000 0
DESC 0;Beginner::Judo
INFO 15;15 0
SAY 0; White Belt to Green Belt server
BOUT 0; 110759 27 12878 1 0 0 Darkvadder 0
BOUT 1; 107851 58 6608 0 1 0 PaiCho 0
BOUT 2; 108420 144 1948 0 2 0 tirititran 0
BOUT 3; 110552 73 8981 0 2 0 [GameOne]cyp 0
BOUT 4; 109377 11 0 0 1 0 Maveric 0
BOUT 5; 109782 88 5380 0 4 0 Bias 0
BOUT 6; 110892 2 0 0 1 0 Re2ry 0
BOUT 7; 108511 11 0 0 1 0 Letterbomb 0
BOUT 8; 110957 3 0 0 1 0 ThaWolff 0
BOUT 9; 110076 71 2114 0 2 0 DarianX 0
BOUT 10; 110917 50 7508 0 1 0 Shiv 0
BOUT 11; 109853 31 901 0 1 0 TatWaffe 0
BOUT 12; 111584 61 6787 0 0 0 [GameOne]Kimmekim 0
BOUT 13; 109981 22 5800 0 1 0 proph3t91 0
BOUT 14; 111071 25 13254 0 1 0 riden 0
BOUT 15; 111615 2877 1058 0 0 9 Juntalis 0
BOUT 16; -1 0 0 0 0 END 0
SPECS 0;
BODCOL 0;0 0 1 0 2 0 3 0 4 0 5 0 6 0 7 0 8 0 9 0 10 0 11 0 12 0 13 0 14 0 15 0 16 0 17 0 18 0 19 0 20 0
GRADCOL1 0;0 0 1 0 2 0 3 0 4 0 5 0 6 0 7 0 8 0 9 0 10 0 11 0 12 0 13 0 14 0 15 0 16 0 17 0 18 0 19 0 20 0
GRADCOL2 0;0 0 1 0 2 0 3 0 4 0 5 0 6 0 7 0 8 0 9 0 10 0 11 0 12 0 13 0 14 0 15 0 16 0 17 0 18 0 19 0 20 0
TRAILCOL 0;0 42 1 42 2 42 3 42
ITEM 0;0 0 0 0 0 0 0 0 0 0 5 0 0 0 0 0 0
TEXBODY 0; 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
BMAPBODY 0; 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
TEXJOINT 0; 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
BMAPJOINT 0; 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
TEXTRAIL 0; 0 0 0 0
TEXGROUND 0; 0
BODCOL 1;0 0 1 0 2 0 3 0 4 0 5 0 6 0 7 0 8 0 9 0 10 0 11 0 12 0 13 0 14 0 15 0 16 0 17 0 18 0 19 0 20 0
GRADCOL1 1;0 0 1 0 2 0 3 0 4 0 5 0 6 0 7 0 8 0 9 0 10 0 11 0 12 0 13 0 14 0 15 0 16 0 17 0 18 0 19 0 20 0
GRADCOL2 1;0 0 1 0 2 0 3 0 4 0 5 0 6 0 7 0 8 0 9 0 10 0 11 0 12 0 13 0 14 0 15 0 16 0 17 0 18 0 19 0 20 0
TRAILCOL 1;0 0 1 0 2 0 3 0
ITEM 1;0 0 0 0 0 0 0 0 0 0 5 0 0 0 0 0 0
TEXBODY 1; 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
BMAPBODY 1; 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
TEXJOINT 1; 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
BMAPJOINT 1; 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
TEXTRAIL 1; 0 0 0 0
TEXGROUND 1; 0
SAY 0; Logged in as Juntalis
SAY 0; 111584 [GameOne]Kimmekim
SAY 0; 109377 Maveric
SAY 0; 108420 tirititran
SAY 0; 109853 TatWaffe
SAY 0; 110759 Darkvadder
SAY 0; 110917 Shiv
SAY 0; 109981 proph3t91
SAY 0; 108511 Letterbomb
SAY 0; 110892 Re2ry
SAY 0; 109782 Bias
SAY 0; 107851 PaiCho
SAY 0; 110957 ThaWolff
SAY 0; 111071 riden
SAY 0; 110076 DarianX
SAY 0; 110552 [GameOne]cyp
SAY 0; 111615 Juntalis


At this point, I no longer get any output from the server, and if I hit control + c, it returns me to the regular console. Watching from an actual game client inside the server I'm connecting to, I see myself connect, and disconnect quickly. Now, I'm doing the protocol completely correct, as it all works properly in telnet. Therefore, there must be something wrong with my source.

You'll note from my source:
strcpy(sendbuf, "NICK Juntalis\nmlogin Juntalis ****\nPING\nstatus\n");
I login, ping the server, and then send a STATUS. All that is sent correctly to the server, as you can see by "Logged in as Juntalis"
Obviously, it goes through the "infinite loop" again, as it wouldn't be able to collect the data to output the fact that I was logged in. So why is it breaking out the loop and ending, I wonder?

ahoodin
June 9th, 2008, 04:55 PM
Perhaps your server does not deal with the carriage return escape code very well. If so it is only a display thing.

'\n'

Q: Does it respond to subsequent echo/pings?

Juntalis
June 9th, 2008, 05:43 PM
Nope, nor does it parse anymore incoming protocol. It just.. Stops.

ahoodin
June 10th, 2008, 07:26 AM
Did you write the server program?

The client will send data to the server and the server will deal with it and send back some response. So you will need a send first. You have a recv in your code.

Of course there are some clients that just open a connection, and the server puts data in and closes the socket. I think in this case you will want to send first though.

Heres the quasi code I think will help you:

ndata = send()
while(ndata)
{
ndata = recv()
send()
}

This is similar to an echo server where the server sends the same data back to the client.

MikeAThon
June 10th, 2008, 09:55 PM
strcpy(sendbuf, "NICK Juntalis\nmlogin Juntalis ****\nPING\nstatus\n");
send(socketDescriptor, sendbuf, strlen(sendbuf) + 1 , 0);
Is there a reason for sending the NULL termination byte? The telnet protocol (with which you tested the correctness of your transmission) would not have sent the NULL termination.

Maybe receipt of the NULL byte is triggering your server to log you off, and disconnect the socket. Try
send(socketDescriptor, sendbuf, strlen(sendbuf) /* + 1 */ , 0);
Mike

Juntalis
June 11th, 2008, 12:09 PM
Wow.. It works! Yeah, I had taken a source I found online, and editted it a bit to match what I needed. The null byte was what was killing it.

//JP added flex table