Sign in to follow this  
Mrafcho001

Asynchronous winsock question

Recommended Posts

I'm trying to make a program where small pieces of data can be exchanged between 2 instances of it over a network. I tried to just use send() and recv() but if one app tries to send 2 things one right after another the 2nd piece of data never reaches its destination. So now im thinking maybe I should try Asynchronous sockets, but from what im reading, im under the impression you cannot have the app send and receive data, it has to be either a server (receive data) or a client (send data) and you cannot have a single application act like a server and a client. Any help would be appreciated, Thanks.

Share this post


Link to post
Share on other sites
Mrafcho001 - Both the client and the server have the ability to send and receive. It is a two-way connection.

When using send() and recv(), the number of bytes sent should match the number of bytes received. You do not have any promise on how many calls it will take to send() or recv() with a TCP/IP connection.

send() returns the number of bytes actually transmitted. You should check to make sure this value is the entirety of the message intended to be sent.

recv() similarly returns the number of bytes read. You should continue to make recv() calls until the total number of bytes recv()ed matches the number of bytes sent().

You will notice that you must define a protocol such that you know how many bytes are expected in a communication between the client <-> server.

Share this post


Link to post
Share on other sites
oh thanks a lot guys...


the problem I'm having though is im transmitting 4 byte (in int) that has the number of bytes to be sent right after, so i can properly allocate memory to recieve the next piece of data.

what is happening is send is saying that all the data has been properly sent, but recv on the other program is showing 0 received bytes and also i get error 10014 every single time!

i checked all pointers, they seem to be properly allocated but i dont know whats happening.

Share this post


Link to post
Share on other sites
heres a simpler example of what i was talking about, it doesnt work, instead of printing out HELLO2 int prints out one character



#include <iostream>
#include <winsock2.h>
#include <windows.h>

using namespace std;
int main()
{
WORD sockVer;
WSADATA wsaData;
int nret;

sockVer = MAKEWORD(2,2);
if(WSAStartup(sockVer, &wsaData) != 0)
cout << "FAILURE" << endl;
else
cout << "SUCCESS" << endl;

SOCKET listening;
SOCKET newcon;
SOCKADDR_IN serveraddr;
SOCKADDR_IN clientaddr;
int port = 5150;

listening = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
serveraddr.sin_family = AF_INET;
serveraddr.sin_port = htons(port);
serveraddr.sin_addr.s_addr = htonl(INADDR_ANY);

if(bind(listening, (SOCKADDR*)&serveraddr, sizeof(serveraddr))!= 0)
{
cout << "bind failure" << endl;
printf("ERROR: %d", WSAGetLastError());
}

if(listen(listening, 5) != 0)
{
cout << "listen failure" << endl;
}

int sizeofclientaddr = sizeof(clientaddr);
newcon = SOCKET_ERROR;
while(1)
{
while(newcon == SOCKET_ERROR)
{
newcon = accept(listening, (SOCKADDR*)&clientaddr, &sizeofclientaddr);
}
cout << "CONNECTION HERE!" << endl;
char buff[256];

recv(newcon, (char*)&buff, 255, 0);

cout << buff << endl;
char buff2[256];
if(newcon == INVALID_SOCKET)
{
cout << "INVALID SOCKET" << endl;
}
int iret = recv(newcon, (char*)&buff2, 255, 0);
if(iret == SOCKET_ERROR)
{
cout << "ERR: " << WSAGetLastError() << endl;
}
cout << "recved: " << iret << endl;
cout << buff2 << endl;
closesocket(newcon);
newcon = SOCKET_ERROR;
}
closesocket(newcon);
closesocket(listening);
WSACleanup();

system("PAUSE");
return 0;

}





#include <iostream>
#include <winsock2.h>
#include <windows.h>

using namespace std;
int main()
{
WORD sockVer;
WSADATA wsaData;

sockVer = MAKEWORD(2,2);
if(WSAStartup(sockVer, &wsaData) != 0)
cout << "FAILURE" << endl;
else
cout << "SUCCESS" << endl;

SOCKADDR_IN serveraddr;
int port = 5150;
SOCKET s;

s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if(s == INVALID_SOCKET)
cout << "INVALID SOCKET" << endl;
serveraddr.sin_family = AF_INET;
serveraddr.sin_port = htons(port);
serveraddr.sin_addr.s_addr = inet_addr("192.168.0.102");

if(connect(s, (SOCKADDR*)&serveraddr, sizeof(serveraddr)) != 0)
{
printf("Erorr: %d", WSAGetLastError());
}

send(s, "HELLO", 6, 0);
int iret = send(s, "HELLO2", 7, 0);
if(iret == SOCKET_ERROR)
{
cout << "\nERROR: " << WSAGetLastError() << endl;
}
cout << "sent: " << iret << endl;
closesocket(s);

WSACleanup();

system("PAUSE");
return 0;

}

Share this post


Link to post
Share on other sites

recv(newcon, (char*)&buff, 255, 0);




should be:

recv(newcon, buff, 255, 0);





Be careful casting types, the compiler was trying to warn you that the &buff was incorrect.

When declaring an array, the array name is a pointer.

Share this post


Link to post
Share on other sites
yeah the first message receives fine, its the 2nd one thats never received.

and in the bigger program thats the actual data that i need, the first message is just the size of the data thats to be followed.

Share this post


Link to post
Share on other sites
Aye. The client performs both send() calls and then closes the socket. Sitting on the server socket is the following data:
"HELLO\0HELLO2\0" (When displaying this buffer, it will stop at the null-term which is placed mid-string)

When the server makes a single recv() call, it will return with 14 bytes - both messages sent by the client.

The second call to recv() will then find the socket to be closed and return with 0 bytes. The second recv() byte count is what you have displayed by the server.

Share this post


Link to post
Share on other sites
If you read the Forum FAQ as I suggested initially, it answers your question perfectly. In short, TCP is not a message protocol, so you can't make 1 send() correspond to 1 recv(). Instead, you have to packetize your stream yourself. The Forum FAQ gives more pointers.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this