Solved

Very Basic Tcp Client-Server C++ Code. Weird Output! Easy Question - Help!

Posted on 2008-11-02
10
1,617 Views
Last Modified: 2012-06-21
I wrote my first client-server in C/C++ under linux by using g++ compiler. My algorithm is fine, the program works, but there is something weird happens at the beginning of output.

Program description: server binds to a port you specify, then keep listening...
client ask for IP & port you want to connect to. Once connected, you send a text
message to the server. Server echos back the same message to you....

Server Interface:

fahmi@Toshiba-Laptop:~/Desktop$ ./a.out
Choose a port to listen on: 2000
waiting for a connection ...
New Client connected from port no 35302 and IP ::aff:40fe:87bf
Sent mesg:
Sent mesg: 1
Sent mesg: Hello There!
Client disconnected

New Client connected from port no 35303 and IP ::ffff:127.0.1.1
************Sent mesg:**************why does this line appear?
Sent mesg: Test Again!
Sent mesg: HEy
Sent mesg: works...
Sent mesg: am out
Client disconnected


Clients Interface:

Enter Server IP: 127.0.1.1
Enter a Port Number: 2000
connecting ...
connection succeeded
***************you: server:*****************why does line appear?

you: Test Again!
server: Test Again!

you: HEy
server: HEy

you: works...
server: works...

you: am out
server: am out

you:
fahmi@Toshiba-Laptop:~/Desktop$

-------------------------------------------------------------------------

Regarding my code structure, i do not see any mean for the places i put asterisks  to appear!!!

It does not effect my code, but its good to know why this happens!

I hope my question is clear....

//**********piece of the server source code:************

.

.

.

.

//listens forever, and accepts all connections that come in

while(1)

{

//accept pending connection. Information of incoming connection will go to clientInfo

clientSockD = accept(serverSockD, &clientInfo, &clientInfo_size);
 

if(clientSockD == ERROR)

{

perror("accept");

return 5;

}
 

clientIP = get_client_addr(&clientInfo);
 

portNum = get_client_port(&clientInfo);
 

inet_ntop(clientInfo.sa_family, clientIP, printableClientIP, sizeof printableClientIP);
 

//convert the port number from network byte order to host byte order

long portHostByte = ntohs(portNum);
 

//print to screen the current clients' IP Address & the port the client's is connected from

printf("New Client connected from port no %d and IP %s\n", portHostByte, printableClientIP);
 

bytes_received = 1;
 

while(bytes_received)

{

bytes_received = recv(clientSockD, data, MAX_DATA, 0);
 

//bytes_received larger than 0, send back to client what client's sent you

if(bytes_received)

{

send(clientSockD, data, bytes_received, 0);

data[bytes_received] = '\0';

printf("Sent mesg: %s", data);

}
 

}
 

printf("Client disconnected\n");

.

.

.
 

//*********************************************************************
 

//**********Piece of the client source code**********************
 

.

.

.
 

while(1)

{

//stores input from screen

cout<<"you: ";

fgets(clientInput, MAX_DATA, stdin);
 

//send input to connected server

send(sockfd, clientInput, strlen(clientInput), 0);
 

int bytes_received = recv(sockfd, serverResponse, MAX_DATA, 0);
 

cout<<"server: ";

serverResponse[bytes_received] = '\0';

printf("%s\n", serverResponse);

}
 

//close the socket

close(sockfd);

.

.

.

.

Open in new window

0
Comment
Question by:F-J-K
10 Comments
 
LVL 68

Expert Comment

by:woolmilkporc
ID: 22861983
Hi,
  did you clear your 'data' and 'ServerResponse' arrays before recv(),
 e.g. bzero(data,123); ?
 wmp
0
 
LVL 1

Author Comment

by:F-J-K
ID: 22862022
I have no idea what that is... :-/, i will google it.
Note: this appears at the very beginning of executing the program only, when recv() has not yet received anything! The client connection just got accepted with no previous background or activities.....
0
 
LVL 53

Assisted Solution

by:Infinity08
Infinity08 earned 100 total points
ID: 22862059
recv can return -1 in case of error. Check for that value before continuing (look at errno to know what the error was).
0
 
LVL 1

Author Comment

by:F-J-K
ID: 22862198
ha right! how come i forgot it!....i'll check it out
0
 
LVL 19

Expert Comment

by:drichards
ID: 22862331
I woudl look on the client side for the problem because the server is just responding to the data sent by the client, and the client output shows that you send a blank something right at the start.  Does that appear right away when you start the program, or does it not appear until you type something and the first data causes two outputs?

If you debug the client and see what is returned from fgets on the first iteration, you shoudl be able to tell what is going on.
0
How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

 
LVL 1

Author Comment

by:F-J-K
ID: 22863950
>>recv can return -1 in case of error. Check for that value before continuing (look at errno to know what the error was).

No errors returned.


>>Does that appear right away when you start the program, or does it not appear until you type something and the first data causes two outputs? If you debug the client and see what is returned from fgets on the first iteration, you shoudl be able to tell what is going on.

Appear right away when you start the program...

hm, i can say everytime program starts, client gets like an empty character or something like that (special weird unseen character) automatically & send it to server, then server replies. Thats why. Now, why this happens :-)...Does fgets() takes a "\0" from the previous input? I have not had fgets() in the code somewhere else....

It works fine when i do cin>>clientInput; instead of fgets(clientInput, MAX_DATA, stdin);
but cin>> only takes one word at a time only :-/. I wanted fget() so i can get whole sentences.



0
 
LVL 1

Author Comment

by:F-J-K
ID: 22864031
Another question:

Bytes sent & received always increased by one.

If i send "hello" from client. Server bytes_received carries 6
client bytes_received carries 6 too.... It should be five....

Any idea?
   
2. bytes_received = recv(clientSockD, data, MAX_DATA, 0);
 if(bytes_received)
{
                                cout<<"Bytes Sent to Client: "<<bytes_received<<endl;
                        send(clientSockD, data, bytes_received, 0);
                        data[bytes_received] = '\0';
                        printf("Sent mesg: %s", data);
                        cout<<"Bytes Sent to Client: "<<bytes_received<<endl;
}

Eventhough, i did it right. I still do not know how '\0' fit into data[bytes_received]...
I know when data is received from clientSocketD, and stored into data[MAX_DATA]. '\0' is dropped. We put '\0' to the array, so it could be printed by using prinf(). My questios is:
bytes_received should get 5 when it receives  "hello" & bytes_received should get 6 when it receives hello\0 ... but as you see, we add null at the end of the array before we print it, so the output of the above code should be as follows:

Bytes Sent to Client: 5
Sent mesg: hello
Bytes Sent to Client: 6

But the output appears on screen is

Bytes Sent to Client: 6
Sent mesg: hello
Bytes Sent to Client: 6

What i think is: array is fixed, when a client send hello - it reaches to server as hello\0 .... 6 bytes
but NULL is dropped, so there is one empty space at the last spot that need to be filled with NULL before pass data to printf() ..... Is this right?

3. why don't we add a parameter in send() that carries '\0' as we know when recv() returned the value, null was dropped. In our case, if we use send(), data will be sent but without NULL, because when received the data, null is dropped. Can you explain it to me please!

My question are long just to make it clear & try to get readers to understand what i'm trying to ask exactly......Thanks for being patience...
0
 
LVL 1

Author Comment

by:F-J-K
ID: 22864169
Regarding the weird output

you: server:

i solved it....

I just put cin.ignore(); before while(1), because as you know cin leaves \0 hanged. Thus, when a function such as getline() get implemented, it will take the last remained character in cin, which is \0. Therefore, i did not get a chance to enter anything at the first time, as the client fgets() grabbed the \0 that is hanged around after i used cin>>remotePort, so i have to use cin.ignore() to let fgets() taking anything from the last standard input. I thought only getline() does this....Anyway, it worked and i hope the concept is right.

I will be glad if i could an answer to above posted questions regarding the number of bytes.
0
 
LVL 19

Accepted Solution

by:
drichards earned 400 total points
ID: 22864666
Two comments:

1) When you use fgets, doesn't the data include the termination character generated by the enter key?  This means that the string will have one more character than you think.  "Hello" for example, is really "Hello\n".  This makes your string length 6 as reported.  When you send, you set the 6th array index to 0 which is really the seventh element and still use bytes_received (which is 6) as the number of bytes to send.  Thus, you send the exact same bytes you receive and you do not send the null string termination.

2) Be careful about how you are receiving because TCP does not guarantee that if you send some number of bytes that they will be received in the same grouping.  UDP does this, but TCP does not.
0
 
LVL 1

Author Closing Comment

by:F-J-K
ID: 31512504
THANKS
0

Featured Post

Top 6 Sources for Identifying Threat Actor TTPs

Understanding your enemy is essential. These six sources will help you identify the most popular threat actor tactics, techniques, and procedures (TTPs).

Join & Write a Comment

Suggested Solutions

Introduction This article is a continuation of the C/C++ Visual Studio Express debugger series. Part 1 provided a quick start guide in using the debugger. Part 2 focused on additional topics in breakpoints. As your assignments become a little more …
I have seen several blogs and forum entries elsewhere state that because NTFS volumes do not support linux ownership or permissions, they cannot be used for anonymous ftp upload through the vsftpd program.   IT can be done and here's how to get i…
The goal of the video will be to teach the user the concept of local variables and scope. An example of a locally defined variable will be given as well as an explanation of what scope is in C++. The local variable and concept of scope will be relat…
The goal of the video will be to teach the user the difference and consequence of passing data by value vs passing data by reference in C++. An example of passing data by value as well as an example of passing data by reference will be be given. Bot…

746 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

11 Experts available now in Live!

Get 1:1 Help Now