I am having trouble with a Winsock2 wrapper classes (client-server) and after countless hours of scratching-my-head-in-confusion, I decided it would be better if I asked your opinion.
To be more specific, the problem is that every time I use my Send() function, both the client and the server (not always!) send one or two extra bytes!
For example I use SendBytes("Hello") and the Recv function returns "Hello•" with a '•' or other random characters at the end of the character array.
//main.cpp (Client)
#include "Socket.h"
int main()
{
NetworkService::Client cService = NetworkService::Client();
int res = cService.Initialize("127.0.0.1","20248");
if(res == 0){
int local = cService.SendBytes("Hello!");
printf("Bytes Sent: %ld\n", local);
cService.Shutdown();
char* temp = cService.Recv();
printf("String Recieved: %s - Size: %d",temp,strlen(temp));
printf("\nSTRLEN: %d",strlen("X5"));
}
else{
cService.Clean();
}
cService.Close();
while(!kbhit());
return 0;
}
Of course, the server sends the string "X5" and the client prints the strlens ...
//The result with "X5" as the dummy text:
String Recieved: X5? - Size: 3 //Notice the extra '?' character
STRLEN: 2
Send // Recieve Functions
int NetworkService::Client::SendBytes(char* lData){
int local = send( ConnectSocket, lData, (int)strlen(lData), 0 );
if (local == SOCKET_ERROR) {
Close();
return WSAGetLastError();
}
return local;
}
char* NetworkService::Client::Recv(){
recv(ConnectSocket, recvbuf , recvbuflen, 0);
return recvbuf;
}
Help would be appreciated ^_^.
Excuse me, but
int local;
(...)
return (int*)local;
What you were trying to achieve? There are many serious problems in your code.
This is not the way you send data over the network. There are too many errors.
IF you want to send null-terminated strings over the network:
int local = send( ConnectSocket, lData, (int)strlen(lData), 0 );
as everyone said, you don't actually send the null terminator. You would have sent it if you added 1 to the length. Moreover, with long strings, the send() function doesn't guarantee you to send the whole string at once. You have to check for that and resend the missing part.
recv(ConnectSocket, recvbuf , recvbuflen, 0);
You don't check the return value, so you can't know the length of the received string. As you don't send the null byte, the received data is not null-terminated. Also, if null terminator is the only delimiter of more data you send, you'll have to read byte-by-byte (not efficient) not to miss the null terminator to know when to finish. An alternative would be to make your own buffering scheme (so the next read would partially return the result of the previous), or change the protocol to make length of the transported data known beforehand. Also, the same remark about partial reads as with the send function applies here.
BTW returning a static/global buffer is not a sign of good code.
You don't really check the return value of recv.
There is a do-while but it doesn't do anything. You return from the function without proper error handling even when recv fails, but you will never know it.
Also you don't send the terminating \0 which isn't necessary bad, depends on what you're trying to do, for example you can add that after receiving.
Related
This is my server program code :
...
listen(s , 3);
//Accept and incoming connection
cout<<"\n\nWaiting for incoming connections... ";
int c = sizeof(sockaddr_in);
Socket newSocket = accept(s , (struct sockaddr *)&client, &c);
if (newSocket == INVALID_SOCKET)
{
cout<<"\nAccept failed with error code : "<<WSAGetLastError();
}
// Since both server and client are now connected, it's time to send and receive players' name
string me;
char other[30];
fi.close(); fi.open("data.dat");
fi>>me; fi.close();
recv(newSocket,other,strlen(other),0);
send(newSocket,me.c_str(),me.length(),0);
cout<<me<<endl<<other;
This is client program code:
Socket s;
//Connect to server
if (connect(s , (sockaddr *)&server , sizeof(server)) < 0)
{
cout<<"\nConnection error.";
_getch();
return 1;
}
//reading name and sending it to server
string me;
char other[30];
ifstream fi("cdata.dat");
fi>>me; fi.close();
send(s,me.c_str(),me.length(),0);
recv(s,other,strlen(other),0);
cout<<me<<endl<<other;
Suppose data.dat contains the word Hero
And cdata.dat contains the word 'Zero'
Now server side output is (ignoring other lines):
Hero
Zero%$#5^sdj
Client side output is (ignoring other lines):
Zero
He
What is the problem?
You are using the function strlen incorrectly here. This determines the length of a c-string by searching for the 1st occurrence of the character \0 (the null terminator). Given that you do not initialise your other array, this value will be random, rather than 30 as you presumably expect.
You can change your code to explicitly state the number 30 as the maximum number of bytes to receive. You can also explicitly send the null terminator by adding 1 to your sent string length. So the server code becomes:
recv(newSocket,other,30,0);
send(newSocket,me.c_str(),me.length()+1,0);
And the client code becomes:
send(s,me.c_str(),me.length()+1,0);
recv(s,other,30,0);
Better still to change the hardcoded 30 to some integer constant, both in the other declaration and in the recv usage above.
your 'other' array is of length 30, but you do not clip the length of that array by the return value of recv which is the number of bytes that were read.
additionally strlen of the other array is dangerous because it's not a null terminated string but a constant size array, you should use the length of this array instead of strlen.
I believe if you do the same in client it will fix that as well. the other array could contain a random null byte when uninitialized which will give an odd strlen value you don't expect.
//server side
void* s2(void *arg){
info *s = (info*)arg;
char buffer[MAXS];
int k;
sockaddr_in addr;
socklen_t aSize = sizeof(sockaddr_in);
int sfd = accept(s->fd,(sockaddr*)&addr,(socklen_t*)&aSize);
if(sfd<0){
s->current--;
pthread_exit(0);
}
while(1){
k = recv(sfd,buffer,MAXS,0);
cout<<buffer<<"\n";
//1. k ==0 socket has been closed by client
//2. k==-1 error in recv
//3. recv quit
if((k==-1)||(!strncmp(buffer,"quit",4))||(k==0))break;
sprintf(buffer,"%d\n",(int)strlen(buffer)); //Convert length to string using sprintf()
send(sfd,buffer,strlen(buffer),0); //send buffer to client
}
close(sfd);
if(s->limit==s->current)
FD_SET(s->fd,&sfds);
s->current--; //decreament the client number
pthread_exit(0);
}
//client side
1. send(sockfd,"sadhdag",8,0);
2. send(sockfd,"ss",3,0);
Server recv sadhdag in first call to recv .
In second call to recv server recv
ss
dag
server side:
function s2 is run by a thread and argument is passed with socket information connection is accepted there and send and recv is called onn newly accepted client.
Why this is happening ? or how to avoid this ?
You're ignoring the count returned by recv(). Contrary to suggestions in comments, it isn't necessary to memset() the buffer to zero before recv(), but it is necessary to only use that buffer afterwards up to that count. For example:
printf("%s", buffer);
is wrong, and
printf("%.*s", count, buffer);
is right.
NB
if((k==-1)||(!strncmp(buffer,"quit",4))||(k==0))break;
isn't correct either. It should be
if((k==-1)||(k==0)||(k >= 4 && !strncmp(buffer,"quit",4))) break;
It isn't valid to look into the buffer at all unless k is positive, and it isn't valid to compare four characters in it unless there are four characters in it.
You forgot to actually implement any kind of protocol or application-level logic of any kind. This sums it up:
k = recv(sfd,buffer,MAXS,0);
cout<<buffer<<"\n";
This code suggests you're terminating your messages with a newline:
sprintf(buffer,"%d\n",(int)strlen(buffer)); //Convert length to string using sprintf()
send(sfd,buffer,strlen(buffer),0); //send buffer to client
If so, where's the code to parse that on the other end? You throw the returned length away, so you wouldn't even know which characters to check for a newline.
TCP is a byte-stream protocol that does not preserve application-level message boundaries. If you want to use it to send strings or other application-level messages, you have to specify and implement an application-level protocol to do it.
You call recv to get the raw TCP data, then you output it as if it was a string. If you're going to define and implement a protocol to send and receive strings over TCP, you have to actually do it. You can't just imagine it happens by magic.
If you want to receive newline-terminated messages into C-style strings, you can certainly do it. But you have to actually write the code to do it.
First question: I am confused between Buffers in TCP. I am trying to explain my proble, i read this documentation TCP Buffer, author said a lot about TCP Buffer, thats fine and a really good explanation for a beginner. What i need to know is this TCP Buffer is same buffer with the one we use in our basic client server program (Char *buffer[Some_Size]) or its some different buffer hold by TCP internally ?
My second question is that i am sending a string data with prefix length (This is data From me) from client over socket to server, when i print my data at console along with my string it prints some garbage value also like this "This is data From me zzzzzz 1/2 1/2....." ?. However i fixed it by right shifting char *recvbuf = new char[nlength>>3]; nlength to 3 bits but why i need to do it in this way ?
My third question is in relevance with first question if there is nothing like TCP Buffer and its only about the Char *buffer[some_size] then whats the difference my program will notice using such static memory allocation buffer and by using dynamic memory allocation buffer using char *recvbuf = new char[nlength];. In short which is best and why ?
Client Code
int bytesSent;
int bytesRecv = SOCKET_ERROR;
char sendbuf[200] = "This is data From me";
int nBytes = 200, nLeft, idx;
nLeft = nBytes;
idx = 0;
uint32_t varSize = strlen (sendbuf);
bytesSent = send(ConnectSocket,(char*)&varSize, 4, 0);
assert (bytesSent == sizeof (uint32_t));
std::cout<<"length information is in:"<<bytesSent<<"bytes"<<std::endl;
// code to make sure all data has been sent
while (nLeft > 0)
{
bytesSent = send(ConnectSocket, &sendbuf[idx], nLeft, 0);
if (bytesSent == SOCKET_ERROR)
{
std::cerr<<"send() error: " << WSAGetLastError() <<std::endl;
break;
}
nLeft -= bytesSent;
idx += bytesSent;
}
std::cout<<"Client: Bytes sent:"<< bytesSent;
Server code:
int bytesSent;
char sendbuf[200] = "This string is a test data from server";
int bytesRecv;
int idx = 0;
uint32_t nlength;
int length_received = recv(m_socket,(char*)&nlength, 4, 0);//Data length info
char *recvbuf = new char[nlength];//dynamic memory allocation based on data length info
//code to make sure all data has been received
while (nlength > 0)
{
bytesRecv = recv(m_socket, &recvbuf[idx], nlength, 0);
if (bytesRecv == SOCKET_ERROR)
{
std::cerr<<"recv() error: " << WSAGetLastError() <<std::endl;
break;
}
idx += bytesRecv;
nlength -= bytesRecv;
}
cout<<"Server: Received complete data is:"<< recvbuf<<std::endl;
cout<<"Server: Received bytes are"<<bytesRecv<<std::endl;
WSACleanup();
system("pause");
delete[] recvbuf;
return 0;
}
You send 200 bytes from the client, unconditionally, but in the server you only receive the actual length of the string, and that length does not include the string terminator.
So first of all you don't receive all data that was sent (which means you will fill up the system buffers), and then you don't terminate the string properly (which leads to "garbage" output when trying to print the string).
To fix this, in the client only send the actual length of the string (the value of varSize), and in the receiving server allocate one more character for the terminator, which you of course needs to add.
First question: I am confused between Buffers in TCP. I am trying to
explain my proble, i read this documentation TCP Buffer, author said a
lot about TCP Buffer, thats fine and a really good explanation for a
beginner. What i need to know is this TCP Buffer is same buffer with
the one we use in our basic client server program (Char
*buffer[Some_Size]) or its some different buffer hold by TCP internally ?
When you call send(), the TCP stack will copy some of the bytes out of your char array into an in-kernel buffer, and send() will return the number of bytes that it copied. The TCP stack will then handle the transmission of those in-kernel bytes to its destination across the network as quickly as it can. It's important to note that send()'s return value is not guaranteed to be the same as the number of bytes you specified in the length argument you passed to it; it could be less. It's also important to note that sends()'s return value does not imply that that many bytes have arrived at the receiving program; rather it only indicates the number of bytes that the kernel has accepted from you and will try to deliver.
Likewise, recv() merely copies some bytes from an in-kernel buffer to the array you specify, and then drops them from the in-kernel buffer. Again, the number of bytes copied may be less than the number you asked for, and generally will be different from the number of bytes passed by the sender on any particular call of send(). (E.g if the sender called send() and his send() returned 1000, that might result in you calling recv() twice and having recv() return 500 each time, or recv() might return 250 four times, or (1, 990, 9), or any other combination you can think of that eventually adds up to 1000)
My second question is that i am sending a string data with prefix
length (This is data From me) from client over socket to server, when
i print my data at console along with my string it prints some garbage
value also like this "This is data From me zzzzzz 1/2 1/2....." ?.
However i fixed it by right shifting char *recvbuf = new
char[nlength>>3]; nlength to 3 bits but why i need to it in this way ?
Like Joachim said, this happens because C strings depend on the presence of a NUL-terminator byte (i.e. a zero byte) to indicate their end. You are receiving strlen(sendbuf) bytes, and the value returned by strlen() does not include the NUL byte. When the receiver's string-printing routine tries to print the string, it keeps printing until if finds a NUL byte (by chance) somewhere later on in memory; in the meantime, you get to see all the random bytes that are in memory before that point. To fix the problem, either increase your sent-bytes counter to (strlen(sendbuf)+1), so that the NUL terminator byte gets received as well, or alternatively have your receiver manually place the NUL byte at the end of the string after it has received all of the bytes of the string. Either way is acceptable (the latter way might be slightly preferable as that way the receiver isn't depending on the sender to do the right thing).
Note that if your sender is going to always send 200 bytes rather than just the number of bytes in the string, then your receiver will need to always receive 200 bytes if it wants to receive more than one block; otherwise when it tries to receive the next block it will first get all the extra bytes (after the string) before it gets the next block's send-length field.
My third question is in relevance with first question if there is
nothing like TCP Buffer and its only about the Char *buffer[some_size]
then whats the difference my program will notice using such static
memory allocation buffer and by using dynamic memory allocation buffer
using char *recvbuf = new char[nlength];. In short which is best and
why ?
In terms of performance, it makes no difference at all. send() and receive() don't care a bit whether the pointers you pass to them point at the heap or the stack.
In terms of design, there are some tradeoffs: if you use new, there is a chance that you can leak memory if you don't always call delete[] when you're done with the buffer. (This can particularly happen when exceptions are thrown, or when error paths are taken). Placing the buffer on the stack, on the other hand, is guaranteed not to leak memory, but the amount of space available on the stack is finite so a really huge array could cause your program to run out of stack space and crash. In this case, a single 200-byte array on the stack is no problem, so that's what I would use.
SOCKET lhSocket;
int iResult;
lhSocket = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
char *sendbuf = "this is a test";
iResult = send(lhSocket, sendbuf, (int)strlen(sendbuf), 0 );
printf("Bytes Sent: %ld\n", iResult);
I have client and Server program using sockets in C++ now i send a buffer it is received by server now when server acknowledge me back saying i got your packet i should get that in string format not bytes received : something. how to achieve that ?
My iresult returns me an integer value, I am sending a message over socket to server , i dont want to print it as Bytes sent : 14.
I want to print the message sent as string to server.
I am dealing with Sockets.
How i can achieve this in C++
stringstream buf;
buf << 12345;
buf.str(); // string("12345")
buf.str().c_str(); // char* "12345"
sendbuf is the string which you are sending. Print sendbuf instead:
printf("Bytes Sent: %s\n", sendbuf);
Another opportunity is boost::lexical_cast<>
const int myIntValue = 12345;
const std::string myStringValue = boost::lexical_cast(myIntValue);
You're asking different things in the title and your post.
Converting int to string in C++ is done with
#include <sstream>
std::ostringstream oss;
oss << some_int;
// do whatever with oss.str()...
as Tomasz illustrated.
To receive data from a socket, you need to make a further call to either recv() or read(). Your "send" call does not itself wait for the reply. recv() or read() accept character-array buffers to read the response into, but you will need to loop reading however much the calls return until you have enough of a response to process, as TCP is what's called a "byte stream" protocol, which means you are not guaranteed to get a complete packet, line, message or anything other than a byte per call.
Given the level of understanding your question implies, I strongly suggest you have a look at the GNU libC examples of sockets programming - there are some server and client examples - easily found via Google.
if you use visual C++ 2008 or 2010 i think there is a function inbuilt to do your job.
something like itoa(int); will convert the given int and return a char *
pretty simple
its in stdlib.hlbtw
** make sure this is not the same in all compilers or distrubutions
http://www.cplusplus.com/reference/clibrary/cstdlib/itoa/
here is a link for reference
Take a look at itoa which converts an integer to a string.
I've got a basic HTTP client set up in C++, which works ok so far. It's for a school assignment, so there's lots more to do, but I'm having a problem.
I use the recv() function in a while loop, to repeatedly add pieces of the response to my response buffer, and then output that buffer each time. The problem is, at the end of each piece of the response, the HTTP Request is getting tacked on as well.
For example, the response will be a chunk of the page's source code, followed by "GET / HTTP/1.1...", followed by the next chunk, and then the "GET..." again, and so on.
Here's my relevant code:
// Prepare request
char request[] = "HEAD /index.html HTTP/1.1\r\nHOST: www.google.com\r\nCONNECTION: close\r\n\r\n";
// Send request
len = send(sockfd, request, sizeof(request), 0);
// Write/output response
while (recv(sockfd, buf, sizeof(buf), 0) != 0)
{
// Read & output response
printf("%s", buf);
}
The buffer isn't null terminated, which is required for strings in C++. When you see the "extra GET", you are seeing memory that you shouldn't be because the stdlib tried to print your buffer, but never found a '\0' character.
A quick fix is to force the buffer to be terminated:
int n = 1;
while (n > 0) {
n = recv(sockfd, buf, sizeof(buf), 0);
if (n > 0) {
// null terminate the buffer so that we can print it
buf[n] = '\0';
// output response
printf("%s", buf);
}
}
I suspect it's because your buf is allocated in memory just below your request. When you call printf on the buffer, printf will print as much as it can before finding a NUL character (which marks the end of the string). If there isn't one, it'll go right on through into request. And generally, there won't be one, because recv is for receiving binary data and doesn't know that you want to treat its output a string.
One quick fix would be to limit the receive operation to sizeof(buf)-1, and to explicitly add the NUL terminator yourself, using the size of the returned data:
while ((nr = recv(sockfd, buf, sizeof(buf), 0)) > 0)
{
buf[nr] = 0;
...
}
Of course, for this to (marginally) safe you need to be sure that you'll always receive printable data.
recv does not add a \0 string terminator to the buffer recieved - it just works in raw binary. So your printf is running off the send of your buf buffer (and apparently ending up looking at your request buffer).
Either add a nul-terminator to the end of buf, or print the buffer one character at a time using putchar() (both of these approaches will make it necessary to store the value returned by recv()).
The recv call will not null-terminate buf; instead, it will just provide you with the raw data received from the wire. You need to save the return value of recv, and then add a null-terminating byte yourself into buf before printing it. Consequentially, you can only ask for sizeof(buf)-1 bytes.