I want to check the existence ( state ) of a server before I send a ZeroMQ request, but I have no idea how to do it.
Q : I want to check the existence ( state ) of a server before I send a ZeroMQ request
The solution is to setup and use the services of a zmq_socket_monitor()
// Read one event off the monitor socket; return value and address
// by reference, if not null, and event number by value. Returns -1
// in case of error.
static int
get_monitor_event ( void *monitor,
int *value,
char **address
)
{
zmq_msg_t msg;
zmq_msg_init ( &msg ); // First frame in message contains event number and value
if ( zmq_msg_recv ( &msg, monitor, 0 ) == -1 ) return -1; // Interrupted, presumably
assert ( zmq_msg_more ( &msg ) & "REASON: Frame #1 FAILED TO SIG 2nd, EXPECTED, FRAME TO COME" );
uint8_t *data = ( uint8_t * ) zmq_msg_data ( &msg );
uint16_t event = *( uint16_t * ) ( data );
if ( value )
*value = *( uint32_t * ) ( data + 2 );
zmq_msg_init ( &msg ); // Second frame in message contains event address
if ( zmq_msg_recv ( &msg, monitor, 0 ) == -1 ) return -1; // Interrupted, presumably
assert ( !zmq_msg_more ( &msg ) & "REASON: Frame #2 FAILED TO SIG more, NOT EXPECTED, FRAMEs TO COME" );
if ( address ) {
uint8_t *data = ( uint8_t * ) zmq_msg_data ( &msg );
size_t size = zmq_msg_size ( &msg );
*address = ( char * ) malloc ( size + 1 );
memcpy ( *address, data, size );
( *address )[size] = 0;
}
return event;
}
int main ( void )
{
void *ctx = zmq_ctx_new ();
assert ( ctx & "REASON: Context FAILED to instantiate" );
void *client = zmq_socket ( ctx, ZMQ_DEALER );
assert ( client & "REASON: Socket FAILED to instantiate" );
// Socket monitoring only works over inproc://
int rc = zmq_socket_monitor ( client, "inproc://monitor-client-side", ZMQ_EVENT_ALL );
assert ( rc == 0 & "REASON: socket_monitor FAILED to instantiate over INPROC:// transport-class" );
// Create socket for collecting monitor events
void *client_side_mon = zmq_socket ( ctx, ZMQ_PAIR );
assert ( client_side_mon & "REASON: socket_monitor receiving Socket FAILED to instantiate " );
// Connect these to the inproc endpoints so they'll get events
rc = zmq_connect ( client_side_mon, "inproc://monitor-client-side" );
assert ( rc == 0 & "REASON: .connect()-method FAILED to get connected" );
// Now do whatever you need
...
// Close client
close_zero_linger ( client );
// --------------------------------------------------------------------
// How to collect and check events from socket_monitor:
int event = get_monitor_event ( client_side_mon, NULL, NULL );
if ( event == ZMQ_EVENT_CONNECT_DELAYED )
event = get_monitor_event ( client_side_mon, NULL, NULL );
assert ( event == ZMQ_EVENT_CONNECTED & "REASON: [client]-socket still not in an expected, .connect()-ed, state" );
...
...
event = get_monitor_event ( client_side_mon, NULL, NULL );
assert ( event == ZMQ_EVENT_MONITOR_STOPPED & "REASON: [client]-socket not in an expected, .close()-ed, state" );
// --------------------------------------------------------------------
// FINALLY:
// --------------------------------------------------------------------
// Close down the sockets
close_zero_linger ( client_side_mon );
zmq_ctx_term ( ctx );
return 0;
}
( included in API since v3.2+ )
You are best off setting up a full connection and devising a simple ACK protocol between the client and server before the sockets is considered to be working normally. If the client receives the ACK within a reasonable time the server is up. Otherwise the server is down, and the client is best closing the socket and trying again until it succeeds.
N.B. If the socket isn't closed, the messages can build up in the ZMQ send queue and risk flooding the server with lots of ACK messages when the server does finally connect.
Related
I have the following simplified IO Completion Port server C++ code:
int main(..)
{
startCompletionPortThreadProc();
// Await client connection
sockaddr_in clientAddress;
int clientAddressSize = sizeof( clientAddress );
SOCKET acceptSocket = WSAAccept( serverSocket, (SOCKADDR*)&clientAddress, &clientAddressSize, NULL, NULL);
// Connected
CreateIoCompletionPort( (HANDLE)acceptSocket, completionPort, 0, 0 );
// Issue initial read
read( acceptSocket );
}
DWORD WINAPI completionPortThreadProc( LPVOID param )
{
DWORD bytesTransferred = 0;
ULONG_PTR completionKey = NULL;
LPPER_IO_DATA perIoData = NULL;
while( GetQueuedCompletionStatus( completionPort, &bytesTransferred, &completionKey, (LPOVERLAPPED*)&perIoData, INFINITE ) )
{
if( WaitForSingleObject( exitEvent, 0 ) == WAIT_OBJECT_0 )
{
break;
}
if( !perIoData )
continue;
if( bytesTransferred == 0 )
{
//TODO
}
switch( perIoData->operation )
{
case OPERATION_READ:
{
// Bytes have been received
if( bytesTransferred < perIoData->WSABuf.len )
{
// Terminate string
perIoData->WSABuf.buf[bytesTransferred] = '\0';
perIoData->WSABuf.buf[bytesTransferred+1] = '\0';
}
// Add data to message build
message += std::tstring( (TCHAR*)perIoData->WSABuf.buf );
// Perform next read
perIoData->WSABuf.len = sizeof( perIoData->inOutBuffer );
perIoData->flags = 0;
if( WSARecv( perIoData->socket, &( perIoData->WSABuf ), 1, &bytesTransferred, &( perIoData->flags ), &( perIoData->overlapped ), NULL ) == 0 )
{
// Part message
continue;
}
if( WSAGetLastError() == WSA_IO_PENDING )
{
// End of message
//TODO: Process message here
continue;
}
}
}
break;
case OPERATION_WRITE:
{
perIoData->bytesSent += bytesTransferred;
if( perIoData->bytesSent < perIoData->bytesToSend )
{
perIoData->WSABuf.buf = (char*)&( perIoData->inOutBuffer[perIoData->bytesSent] );
perIoData->WSABuf.len = ( perIoData->bytesToSend - perIoData->bytesSent);
}
else
{
perIoData->WSABuf.buf = (char*)perIoData->inOutBuffer;
perIoData->WSABuf.len = _tcslen( perIoData->inOutBuffer ) * sizeof( TCHAR );
perIoData->bytesSent = 0;
perIoData->bytesToSend = perIoData->WSABuf.len;
}
if( perIoData->bytesToSend )
{
if( WSASend( perIoData->socket, &( perIoData->WSABuf ), 1, &bytesTransferred, 0, &( perIoData->overlapped ), NULL ) == 0 )
continue;
if( WSAGetLastError() == WSA_IO_PENDING )
continue;
}
}
break;
}
}
return 0;
}
bool SocketServer::read( SOCKET socket, HANDLE completionPort )
{
PER_IO_DATA* perIoData = new PER_IO_DATA;
ZeroMemory( perIoData, sizeof( PER_IO_DATA ) );
perIoData->socket = socket;
perIoData->operation = OPERATION_READ;
perIoData->WSABuf.buf = (char*)perIoData->inOutBuffer;
perIoData->WSABuf.len = sizeof( perIoData->inOutBuffer );
perIoData->overlapped.hEvent = WSACreateEvent();
DWORD bytesReceived = 0;
if( WSARecv( perIoData->socket, &( perIoData->WSABuf ), 1, &bytesReceived, &( perIoData->flags ), &( perIoData->overlapped ), NULL ) == SOCKET_ERROR )
{
int gle = WSAGetLastError();
if( WSAGetLastError() != WSA_IO_PENDING )
{
delete perIoData;
return false;
}
}
return true;
}
bool SocketServer::write( SOCKET socket, std::tstring& data )
{
PER_IO_DATA* perIoData = new PER_IO_DATA;
ZeroMemory( perIoData, sizeof( PER_IO_DATA ) );
perIoData->socket = socket;
perIoData->operation = OPERATION_WRITE;
perIoData->WSABuf.buf = (char*)data.c_str();
perIoData->WSABuf.len = _tcslen( data.c_str() ) * sizeof( TCHAR );
perIoData->bytesToSend = perIoData->WSABuf.len;
perIoData->overlapped.hEvent = WSACreateEvent();
DWORD bytesSent = 0;
if( WSASend( perIoData->socket, &( perIoData->WSABuf ), 1, &bytesSent, 0, &( perIoData->overlapped ), NULL ) == SOCKET_ERROR )
{
if( WSAGetLastError() != WSA_IO_PENDING )
{
delete perIoData;
return false;
}
}
return true;
}
1) The first issue I have is with the initial read.
On client connection (accept), I issue a read. As the client hasn't sent any data yet, WSAGetLastError() is WSA_IO_PENDING and the read method returns.
When the client then sends data, the thread remains stuck in the GetQueuedCompletionStatus call (as I assume I need another WSARecv call?).
Am I supposed to keep looping the read method until data arrives? That doesn't seem logical, I thought by issuing the initial read GetQueuedCompletionStatus would complete when data arrived.
2) I need to read and write data bi-directional without acknowledgements. Therefore I've also created a client with the IOCP thread. Is it actually possible to do this with completion ports or does a read have to be followed by a write?
Sorry for what feels like basic questions, but after trawling the internet and building IOCP examples I'm still unable to answer the questions.
Many thanks in advance.
On client connection (accept), I issue a read. As the client hasn't sent any data yet, WSAGetLastError() is WSA_IO_PENDING and the read method returns.
That is normal behavior.
When the client then sends data, the thread remains stuck in the GetQueuedCompletionStatus call (as I assume I need another WSARecv call?).
No, you do not need another call. And if it is getting stuck, then you are not associating the read with the I/O Completion Port correctly.
Am I supposed to keep looping the read method until data arrives?
No. You need to call WSARecv() one time for the initial read. The WSA_IO_PENDING error means the read is waiting for data and will signal the I/O Completion Port when data actually arrives. DO NOT call WSARecv() (or any other read function) until that signal actually arrives. Then you can call WSARecv() again to wait for more data. Repeat until the socket is disconnected.
I thought by issuing the initial read GetQueuedCompletionStatus would complete when data arrived.
That is exactly what is supposed to happen.
2) I need to read and write data bi-directional without acknowledgements. Therefore I've also created a client with the IOCP thread. Is it actually possible to do this with completion ports
Yes. Reading and writing are separate operations, they are not dependent on each other.
does a read have to be followed by a write?
Not if your protocol does not require it, no.
Now, with that said, there are some issues with your code.
On a minor note, WSAAccept() is synchronous, you should consider using AcceptEx() instead so it can use the same I/O Completion Port for reporting new connections.
But more importantly, when a pending I/O operation fails, GetQueuedCompletionStatus() returns FALSE, the returned LPOVERLAPPED pointer will be non-NULL, and GetLastError() will report why the I/O operation failed. However, if GetQueuedCompletionStatus() itself fails, the returned LPOVERLAPPED pointer will be NULL, and GetLastError() will report why GetQueuedCompletionStatus() failed. This difference is clearly explained in the documentation, but your while loop is not accounting for it. Use a do..while loop instead and act according to the LPOVERLAPPED pointer:
DWORD WINAPI completionPortThreadProc( LPVOID param )
{
DWORD bytesTransferred = 0;
ULONG_PTR completionKey = NULL;
LPPER_IO_DATA perIoData = NULL;
do
{
if( GetQueuedCompletionStatus( completionPort, &bytesTransferred, &completionKey, (LPOVERLAPPED*)&perIoData, INFINITE ) )
{
// I/O success, handle perIoData based on completionKey as needed...
}
else if( perIoData )
{
// I/O failed, handle perIoData based on completionKey as needed...
}
else
{
// GetQueuedCompletionStatus() failure...
break;
}
}
while( WaitForSingleObject( exitEvent, 0 ) == WAIT_TIMEOUT );
return 0;
}
On a side note, instead of using an event object to signal when completionPortThreadProc() should exit, consider using PostQueuedCompletionionStatus() instead to post a termination completionKey to the I/O Completion Port, then your loop can look for that value:
DWORD WINAPI completionPortThreadProc( LPVOID param )
{
DWORD bytesTransferred = 0;
ULONG_PTR completionKey = NULL;
LPPER_IO_DATA perIoData = NULL;
do
{
if( GetQueuedCompletionStatus( completionPort, &bytesTransferred, &completionKey, (LPOVERLAPPED*)&perIoData, INFINITE ) )
{
if( completionKey == MyTerminateKey )
break;
if( completionKey == MySocketIOKey )
{
// I/O success, handle perIoData as needed...
}
}
else if( perIoData )
{
// I/O failed, handle perIoData based on completionKey as needed...
}
else
{
// GetQueuedCompletionStatus() failure...
break;
}
}
while( true );
return 0;
}
CreateIoCompletionPort( (HANDLE)acceptSocket, completionPort, MySocketIOKey, 0 );
PostQueuedCompletionStatus( completionPort, 0, MyTerminateKey, NULL );
Hi I am using winsock2 and I am trying to get async communication.
I tried with TCP server msdn which is waiting for accept.
I tried with WSAAsyncSelect before the listen function.
WSAAsyncSelect(ListenSocket,
m_hWnd,
WM_SOCKET,
(FD_CLOSE | FD_ACCEPT | FD_READ));
and is showing the following error ..
Error C4996 'WSAAsyncSelect': Use WSAEventSelect() instead or define _WINSOCK_DEPRECATED_NO_WARNINGS to disable deprecated API warnings
How can I solve this .. Thanks in advance ..
To get rid of that warning you can define #define _WINSOCK_DEPRECATED_NO_WARNINGS
at the top of your source file, which will disable there types of warnings.
That said, it might be worth listening to this warning and using WSAEventSelect instead.
Since WSAEventSelect signals an event instead of posting a message to the Window's message queue which is what WSAAsyncSelect does. Posting into the message queue is slower and adds additional processing that isn't really needed.
I have an example laying around which i'll post here for you:
... I may have gone overboard... but it's all useful and relevant.
Setup Listening Socket
if ( socket_name == INVALID_SOCKET )
{
P_ERR( "Could not create socket ( Id: %d ): %d\n", id, WSAGetLastError() );
return INVALID_SOCKET;
}
rerror = bind( socket_name, (SOCKADDR*)&sock_addr, sizeof( sock_addr ) );
if ( rerror != SOCKET_ERROR )
{
rerror = listen( socket_name, MAX_LISTEN_QUEUE );
if ( rerror != SOCKET_ERROR )
{
/* Selects the events that will trigger the `socket_event` windows event. */
/* socket_event was created using 'CreateEvent( NULL, TRUE, FALSE, NULL );' */
WSAEventSelect( socket_name, socket_event, FD_ALL_EVENTS );
if ( !startStatusThread() )
{
rerror = 1;
P_ERR( "Status thread failed: %d\n", id );
}
}
else
{
P_ERR( "listen() error %d : Error %d\n", id, WSAGetLastError() );
closesocket( socket_name );
}
}
else
{
P_ERR( "bind() error ( Id: %d ): %d\n", id, WSAGetLastError() );
closesocket( socket_name );
}
Process Events From Socket
/* waits 10ms for events in the event array ( in this case just 1 event as socket_event ). */
rerror = WSAWaitForMultipleEvents( 1, &socket_event, FALSE, 10, FALSE );
if ( rerror == WSA_WAIT_TIMEOUT )
{
continue; /* this block of code runs in a while loop. */
}
index = rerror - WSA_WAIT_EVENT_0; /* get the smallest index of a triggered event */
if ( rerror != WSA_WAIT_TIMEOUT && rerror != WSA_WAIT_FAILED )
{
/* returns a list of the events that occured. */
rerror = WSAEnumNetworkEvents( socket_name, socket_event, &events );
if ( rerror == SOCKET_ERROR )
{
P_ERR( "WSAEnumNetworkEvents Error %d: Id: %d\n", WSAGetLastError(), pThis->id );
continue;
}
/* look below for this function. */
handleNetworkEvents( events, index );
}
Handling the Events.
void
handleNetworkEvents( WSANETWORKEVENTS e, const int socket_index )
{
int rerror = 0;
/* on accept. */
if ( e.lNetworkEvents & FD_ACCEPT )
{
if ( e.iErrorCode[FD_ACCEPT_BIT] == 0 )
{
onAccept();
}
else
{
P_ERR( "Unknown network event error %d\n", id );
}
}
/* on connect */
if ( e.lNetworkEvents & FD_CONNECT )
{
if ( e.iErrorCode[FD_CONNECT_BIT] == 0 )
{
sendRead(); /* send first read request */
}
else
{
P_ERR( "Unknown network event error %d\n", id );
}
}
/* on successful read */
if ( e.lNetworkEvents & FD_READ )
{
sendRead(); /* get read data and queue another request. */
callback( id, inBuffer.buf, lastReadSize ); /* process data. */
}
/* on close. */
if ( e.lNetworkEvents & FD_CLOSE )
{
/* close the current event and make a new one ready for a new connection. */
onClose( socket_index );
}
}
I have a socket connect function, the issue is that if the client is started before the server, the connection shows as connected, but for some reason returns fails. I am not sure where the failure is and would really appreciate any help:
The function is:
bool IPV4Socket::Connect( std::string hostname
, unsigned short remotePort
, TimeoutValue *timeout )
{
AddrInfo getResults;
AddrInfo getaddrinfoHints;
int connReturn = 0;
SockAddr_In *addrData;
bool connectSuccess = false;
std::string service = std::to_string( remotePort );
getaddrinfoHints.ai_family = AddressFamily_inet;
getaddrinfoHints.ai_socktype = SockType_stream;
if ( m_socketAdaptor->getaddrinfo( hostname
, service
, &getaddrinfoHints
, &getResults ) != 0 )
{
return false;
}
addrData = (SockAddr_In *)&( *getResults.ai_addr.begin() );
connReturn = m_socketAdaptor->connect( m_socket
, (const Sockaddr *)addrData
, (int)getResults.ai_addrlen );
if ( connReturn == SocketError)
{
int m_lastErrorCode = m_socketAdaptor->GetLastError();
// Connection error : FATAL
if ( ( m_lastErrorCode != SockErr_EWOULDBLOCK) &&
( m_lastErrorCode != SockErr_EALREADY ) )
{
connectSuccess = false;
}
else
{
SocketSet writeFDS;
SocketSet exceptFDS;
int selectReturn = 0;
// Clear all the socket FDS structures
SocketSet_ZERO( &writeFDS );
SocketSet_ZERO( &exceptFDS );
// Put the socket into the FDS structures
SocketSet_SET( m_socket, &writeFDS );
SocketSet_SET( m_socket, &exceptFDS );
selectReturn = m_socketAdaptor->select( -1
, NULL
, &writeFDS
, &exceptFDS
, timeout );
if ( selectReturn == SocketError )
{
// Any errors are bad
connectSuccess = false;
}
else if ( selectReturn > 0 )
{
// Check for error (exception) first
if ( m_socketAdaptor->SocketSet_ISSET( m_socket, &exceptFDS ) )
{
connectSuccess = false;
}
else if ( m_socketAdaptor->SocketSet_ISSET( m_socket, &writeFDS ) )
{
// Select returned 'writable', we're connected!
connectSuccess = true;
m_isConnected = true;
}
}
}
}
else
{
connectSuccess = true;
m_isConnected = true;
}
return connectSuccess;
}
I am not sure if I am missing the point, or if I have overly complicated the function.
Helllp :)
Notes:
* By the way, m_socketAdaptor-> functions are just wrappers.
* If you start server and then client, it works...
You can't reconnect a socket which has already failed to connect. You have to close it and create a new socket. Therefore that should be done in the connect method, not wherever it is done now.
I'm trying to get a simple multicasting example to work on Linux (I've
tried both RHEL 4 2.6.9 and Ubuntu 8.04 2.6.24). The general idea is
that I would like the server to bind to a unicast address and then add
itself to the group ff02::1. I would then like it to receive
multicasts sent to ff02::1. The code below works on Mac OS X 10.5 (in
fact, a server running on OS X gets multicasts sent from Linux
clients), but I can't get the Linux server side to work. It doesn't
get any multicasts. If I change the code to bind to :: (INADDR6_ANY)
rather than a unicast address (I've tried both link-local and global
addresses), it does get the multicasts. I was wondering if someone
could point out what I'm doing wrong.
server:
memset( &hint, 0, sizeof( hint ) );
hint.ai_family = AF_INET6;
hint.ai_socktype = SOCK_DGRAM;
// argv[1] is either a link-local or a global address
err = getaddrinfo( argv[1], NULL, &hint, &info );
if( err != 0 ) {
perror( "getaddrinfo" );
exit( 1 );
}
struct sockaddr_in6 * addr = (struct sockaddr_in6*)info->ai_addr;
//addr->sin6_addr = in6addr_any; // if this is uncommented, multicasts are received
addr->sin6_port = htons( 7890 );
s = socket( AF_INET6, SOCK_DGRAM, 0 );
if( bind( s, (struct sockaddr*) addr, info->ai_addrlen ) != 0 ) {
close( s );
perror( "bind" );
exit( 1 );
}
if( getaddrinfo( "ff02::1", NULL, &hint, &multi ) != 0 ) {
close( s );
perror( "getaddrinfo" );
exit( 1 );
}
struct ipv6_mreq mreq;
memset( &mreq, 0, sizeof(mreq) );
memcpy( &mreq.ipv6mr_multiaddr, &((struct sockaddr_in6 *) multi->ai_addr)->sin6_addr, sizeof(mreq.ipv6mr_multiaddr) );
mreq.ipv6mr_interface = 2; // 2 happens to be the interface ID; I've tried other values here
freeaddrinfo( multi );
if( setsockopt( s, IPPROTO_IPV6, IPV6_JOIN_GROUP, &mreq, sizeof(mreq) ) != 0 ) {
close( s );
perror( "IPV6_JOIN_GROUP" );
exit( 1 );
}
for( ; ; ) {
char data[6];
size_t len;
len = recvfrom( s, data, 5, 0, NULL, NULL );
data[5] = '\0';
printf( "Received %s\n", data );
if( strcmp( data, "exitt" ) == 0 ) {
break;
}
}
The client code is as follows:
memset( &hint, 0, sizeof( hint ) );
hint.ai_family = AF_INET6;
hint.ai_socktype = SOCK_DGRAM;
hint.ai_protocol = 0;
err = getaddrinfo( "ff02::1", NULL, &hint, &info );
if( err != 0 ) {
perror( "getaddrinfo" );
return 0;
}
struct sockaddr_in6 * addr = (struct sockaddr_in6*)info->ai_addr;
addr->sin6_port = htons( 7890 );
addr->sin6_scope_id = 2; // 2 happens to be the interface ID
s = socket( AF_INET6, SOCK_DGRAM, 0 );
for( ; ; ) {
char data[6];
size_t len;
scanf( "%5s", data );
data[5] = '\0';
printf( "Sending %s\n", data );
if( sendto( s, data, 5, 0, info->ai_addr, info->ai_addrlen ) != 5 ) {
printf( "Error sending\n" );
}
if( strcmp( data, "exitt" ) == 0 ) {
break;
}
}
close( s );
Binding filters incoming addresses, so if you bind to an adapter address you only get packets with matching destination address: i.e. unicast packets, if you bind to a multicast address you will only get multicast packets; to get multicast and unicast packets you must bind to INADDR_ANY or IN6ADDR_ANY.
void CApplication::SendData( const char pBuffer[] )
{
if( pBuffer == NULL )
{
Log()->Write( ELogMessageType_ERROR, "Cannot send NULL message.");
return;
}
// calculate the size of that data
unsigned long messageSize = strlen( pBuffer );
// fix our byte ordering
messageSize = htonl( messageSize );
if( isServer == true )
{
for( unsigned int i = ESocket_CLIENT0; i < ESocket_MAX; ++i )
{
// send the message size
if( m_Socket[ i ] > 0 )
{
if( send( m_Socket[ i ], (char*)&messageSize, sizeof( messageSize ), 0 ) == SOCKET_ERROR )
{
Log()->Write( ELogMessageType_ERROR, "[Application] Send error: %i to socket %i", WSAGetLastError(), m_Socket[ i ] );
continue;
}
// fix our message size back to host ordering
messageSize = ntohl(messageSize);
// send the actual message
if( send( m_Socket[ i ], pBuffer, messageSize, 0 ) == SOCKET_ERROR )
{
Log()->Write( ELogMessageType_ERROR, "[Application] Send error: %i to socket %i", WSAGetLastError(), m_Socket[ i ] );
continue;
}
Log()->Write( ELogMessageType_MESSAGE, "[Application] SEND: %s", pBuffer );
}
}
}
You're not handling the case where send() sends less data than you've asked it to. You need to loop if that is the case, until all data has gone out. You're also not handling errors in general, if a client has disconnected, send() might return -1 for instance.
The typical approach is something like::
for(size_t to_go = messageSize; to_go > 0;)
{
int put = send(sock, buf, to_go);
if(put < 0)
{
perror("Socket send() error");
break;
}
buf += put;
to_go -= put;
}
This attempts to send the entire remaining message, until all of it has been sent. You will of course need to adapt for your specific variable names, do better error-handling, and so on; please view the above as a sketch.