After a lot of TCP fighting...

I arrived to this, which isn't as bad as the one I did this morning:

DWORD WINAPI tcpThread::serverthread_run(LPVOID lparam)
{

sockaddr_in sock;
int porta=(int)lparam;
MessageBox(NULL,"Ale'!","Fanculo",MB_OK);

sock.sin_family=AF_INET; //Address family
sock.sin_addr.s_addr=inet_addr("192.168.0.71"); //Wild card IP address
sock.sin_port=htons((u_short)porta); //port to use

SOCKET serverSock=socket(AF_INET,SOCK_STREAM,0);

if(serverSock==INVALID_SOCKET)
{
int errorSock=WSAGetLastError();
MessageBox(NULL,"socket() error","Oh!",MB_OK);
return 0; //CTRL_INIT_ERROR;
}

int errorBind=bind(serverSock,(struct sockaddr*)&sock,sizeof(sock));

if(errorBind==SOCKET_ERROR)
{
int errorNew=WSAGetLastError();
MessageBox(NULL,"Bind() error","Oh!",MB_OK);
return 0; //BIND_ERROR;

}


for(;;)
{

if (listen(serverSock,1)==-1) {

MessageBox(NULL,"Listen() error", "Oh!",MB_OK);
return 0;
}

SOCKET client;
sockaddr_in from;
int fromlen=sizeof(from);

client=accept(serverSock,(struct sockaddr*)&from,&fromlen);

char temp[512];
char temp2[512];

int data=recv(client,temp2,sizeof(temp2),0);

sprintf(temp,"Your IP is %s\r\n",inet_ntoa(from.sin_addr));
send(client,temp,strlen(temp),0);


closesocket(client);


}

WSACleanup();

return 0;
}

The fact is, I want this thread to continuously answer clients; instead, whenm the first client connection works well; the second doesn't connect and gives me an error; the third works well again etc. I think there's somethinbg to fix in the loop, but I can't figure it out.
Thanks.
[2179 byte] By [ZillionDollarSadist] at [2007-11-19 7:24:28]
# 1 Re: After a lot of TCP fighting...
Have you looked at GetLastError() after the failure?

Have you looked at the winsock errors? WSA_WAIT_TIMEOUT etc?

After the failure run netstat and see what the connection state is.

Make sure you read this article and understand what state your socket is being left in:

http://tangentsoft.net/wskfaq/articles/debugging-tcp.html

HTH,

ahoodin

PS Additionally how are you ascertaining packet length on the client after you send the string back to it? Can you post a .zip with the client and server code?
ahoodin at 2007-11-9 13:49:14 >
# 2 Re: After a lot of TCP fighting...
I forgot - the client gives me an arror, more precisely it stops with a "10054" error, which is "connection reset by peer". I suppose I have to close the socket gracefully, but I don't get it quite well...
The client hasn't been written by me (yet - I have to rewrite it soon), anyway it uses vcl (Borland) socket components.
Thanks!
ZillionDollarSadist at 2007-11-9 13:50:15 >
# 3 Re: After a lot of TCP fighting...
This is an error on your server.

Your server is resetting the connection.

This could happen because your socket listener/server is having an exception.

Also this could happen if your trying to send data and the server is not accepting it anymore. Your Client and server may be out of sync.

With Microsoft, every packet has to be ACKed. ( Look at the state diagram in the link I forwarded you). Get a packet sniffer and sniff around to learn more.

The client send()s out some data, and then the server recv()s that data and send()s some data to the client which recv()s that data. The client has to recv all the data before it moves on, so you have to have some scheme for the client to know how many times to call recv()/how much data to recv(). If you didn't write the client you are probably using an echo client which is expecting the same amount of data you just sent to the server back from the server.

You have to write a custom client.

HTH,

ahoodin

PS If this helps dont forget to rate!
ahoodin at 2007-11-9 13:51:17 >
# 4 Re: After a lot of TCP fighting...
The client send()s out some data, and then the server recv()s that data and send()s some data to the client which recv()s that data. The client has to recv all the data before it moves on, so you have to have some scheme for the client to know how many times to call recv()/how much data to recv(). If you didn't write the client you are probably using an echo client which is expecting the same amount of data you just sent to the server back from the server.

So I'll write a working client syncronized with the server (sending appropriate ACK signals), then.
There's one thing I need to know: when the server is running, it should go on forever waiting for connection: is the endless loop above a correct way of doing it?
Thnaks a lot!
ZillionDollarSadist at 2007-11-9 13:52:14 >
# 5 Re: After a lot of TCP fighting...
You will need to bind() to the socket, set the socket to listen() and then accept() incoming connections:

if (bind(servSock,(struct sockaddr *)&ServAddr,sizeof(ServAddr)) < 0)
DieWithError("bind() failed");

if (listen(servSock,MAXPENDING) < 0 )
DieWithError("listen() failed");

for (;;)
{
clntLen = sizeof(ClntAddr);

if ((clntSock = accept(servSock, (struct sockaddr*) &ClntAddr, (int*)&clntLen)) < 0)
DieWithError("accept() failed.");

HandleClient(clntSock);

}
}
void HandleClient(int clntSock)
{
char echoBuffer[RCVBUFSIZE];
int rcvMsgSize=0,totrcv=0;
if ((rcvMsgSize = recv(clntSock, echoBuffer, RCVBUFSIZE, 0)) < 0)
DieWithError("recv() failed.");
totrcv=rcvMsgSize;
while (rcvMsgSize > 0)
{
if (send(clntSock, echoBuffer, rcvMsgSize, 0) != rcvMsgSize)
DieWithError("Send() failed");

if ((rcvMsgSize = recv(clntSock, echoBuffer, RCVBUFSIZE,0)) < 0)
DieWithError("recv() failed");
totrcv+=rcvMsgSize;
}
closesocket(clntSock);
}
ahoodin at 2007-11-9 13:53:25 >
# 6 Re: After a lot of TCP fighting...
Thanks for the suggestions.
I have now problems on the client side: the failing of connect(), which seems odd since I think I call it normally.

sockaddr_in localSock;
localSock.sin_family=AF_INET; //Address family
localSock.sin_addr.s_addr=inet_addr("127.0.0.1"); //IP address - local host
localSock.sin_port=htons((u_short)2003); //port to use

SOCKET clientSock=socket(AF_INET, SOCK_STREAM, 0);

if (connect(clientSock, (sockaddr*)&localSock, sizeof(sockaddr_in)) == SOCKET_ERROR) {
clientSock = INVALID_SOCKET;
MessageBox(NULL,"Connect() error, ****!","Oh!",MB_OK);}

Obviously, I always get the error window and I can't figure it out.
Thanks again!
ZillionDollarSadist at 2007-11-9 13:54:24 >
# 7 Re: After a lot of TCP fighting...
Check the parameters.

What port is your server on?

What does GetLastError() tell you?

What OS?

Please post your server code.

ahoodin
ahoodin at 2007-11-9 13:55:17 >
# 8 Re: After a lot of TCP fighting...
Please post your server code.

ahoodin
ahoodin at 2007-11-9 13:56:21 >
# 9 Re: After a lot of TCP fighting...
Ok.
System: Windows XP

Complete client Thread:

DWORD WINAPI tcpThread::clientthread_run(LPVOID lparam)
{

const int kBufferSize=1024;
const char* kpcEchoMessage = "This is a test of the emergency data "
"transfer system. If this had been real a real emergency, we "
"would have sent this data out-of-band.";
const int kEchoMessageLen = strlen(kpcEchoMessage);
const int kShutdownDelay = 3;

//Client socket locale
sockaddr_in localSock;
localSock.sin_family=AF_INET; //Address family
localSock.sin_addr.s_addr=inet_addr("127.0.0.1"); //IP address
localSock.sin_port=htons((u_short)2003); //port to use

//Connessione al server
sockaddr_in* addr=(sockaddr_in*) lparam;
SOCKET clientSock=socket(AF_INET, SOCK_STREAM, 0);

if (clientSock==INVALID_SOCKET) {MessageBox(NULL,"Creazione socket:una merda","Oh!",MB_OK);}

if (connect(clientSock, (sockaddr*)&localSock, sizeof(sockaddr_in)) == SOCKET_ERROR) {
clientSock = INVALID_SOCKET;
MessageBox(NULL,"Socket rancido nel client","Oh!",MB_OK);

}
//-------

//Manda stringa al server
if (send(clientSock, kpcEchoMessage, kEchoMessageLen, 0) == SOCKET_ERROR) {

MessageBox(NULL,"Spedizione andata a male", "De'",MB_OK);

int error=WSAGetLastError();

switch (WSAGetLastError())
{
case WSANOTINITIALISED:
MessageBox(NULL,"A successful WSAStartup must occur before using this function","Oh!",MB_OK);
break;
case WSAENETDOWN:
MessageBox(NULL,"The network subsystem has failed","Oh!",MB_OK);
break;
case WSAEADDRINUSE:
MessageBox(NULL,"The specified address is already in use","Oh!",MB_OK);
break;
case WSAEINTR:
MessageBox(NULL,"The (blocking) call was canceled through WSACancelBlockingCall","Oh!",MB_OK);
break;
case WSAEINPROGRESS:
MessageBox(NULL,"A blocking Windows Sockets 1.1 call is in progress, or the service provider is still processing a callback function","Oh!",MB_OK);
break;
case WSAEALREADY:
MessageBox(NULL,"A nonblocking connect call is in progress on the specified socket","Oh!",MB_OK);
break;
case WSAEADDRNOTAVAIL:
MessageBox(NULL,"The specified address is not available from the local machine","Oh!",MB_OK);
break;
case WSAEAFNOSUPPORT:
MessageBox(NULL,"Addresses in the specified family cannot be used with this socket","Oh!",MB_OK);
break;
case WSAECONNREFUSED:
MessageBox(NULL,"The attempt to connect was forcefully rejected","Oh!",MB_OK);
break;
case WSAEFAULT:
MessageBox(NULL,"The name or the namelen argument is not a valid part of the user address space, the namelen argument is too small, or the name argument contains incorrect address format for the associated address family","Oh!",MB_OK);
break;
case WSAEINVAL:
MessageBox(NULL,"The parameter s is a listening socket, or the destination address specified is not consistent with that of the constrained group the socket belongs to","Oh!",MB_OK);
break;
case WSAEISCONN:
MessageBox(NULL,"The socket is already connected (connection-oriented sockets only)","Oh!",MB_OK);
break;
case WSAENETUNREACH:
MessageBox(NULL,"The network cannot be reached from this host at this time","Oh!",MB_OK);
break;
case WSAENOBUFS:
MessageBox(NULL,"No buffer space is available. The socket cannot be connected","Oh!",MB_OK);
break;
case WSAENOTSOCK:
MessageBox(NULL,"The descriptor is not a socket","Oh!",MB_OK);
break;
case WSAETIMEDOUT:
MessageBox(NULL,"Attempt to connect timed out without establishing a connection","Oh!",MB_OK);
break;
case WSAEWOULDBLOCK:
MessageBox(NULL,"The socket is marked as nonblocking and the connection cannot be completed immediately. It is possible to select the socket while it is connecting by selecting it for writing","Oh!",MB_OK);
break;
case WSAEACCES:
MessageBox(NULL,"Attempt to connect datagram socket to broadcast address failed because setsockopt SO_BROADCAST is not enabled","Oh!",MB_OK);
break;
}
}
//--------

//Ricevi risposta dal server
char acReadBuffer[kBufferSize];
int nTotalBytes = 0;

while (nTotalBytes < kEchoMessageLen) {

int nNewBytes = recv(clientSock, acReadBuffer + nTotalBytes,kBufferSize - nTotalBytes, 0);
if (nNewBytes == SOCKET_ERROR) {
return -1;
}

else if (nNewBytes == 0) {

MessageBox(NULL,"Connessione resettata dal piiir","Oh",MB_OK);
}

nTotalBytes += nNewBytes;
}

//Qui si controlla che i dati siano tutti a posto
if (strncmp(acReadBuffer, kpcEchoMessage, nTotalBytes) == 0) {
MessageBox(NULL,"Risposta ok!","Oh!",MB_OK);
}

else {
MessageBox(NULL,"Qualcosa nei dati si e' sbombolato", "Oh!",MB_OK);
}

//--------

//Controllo errori vari
int nBytes;
if (nTotalBytes>0) {

if (nTotalBytes==kBufferSize) {

MessageBox(NULL,"Qualche troiaio, forse overflow", "Oh!",MB_OK);
}

} else if (nTotalBytes==0) {

MessageBox(NULL,"Connessione chiusa a cavolo","Oh!",MB_OK);

} else {

MessageBox(NULL,"Altri errori scassanti","Oh!",MB_OK);

}

}

There's an init() function eslsewhere calling WSADATA and all its initialization, so that's not the error.

I followed the tangentsoft basic server/client example as a blueprint for my frankensteinware.
ZillionDollarSadist at 2007-11-9 13:57:19 >
# 10 Re: After a lot of TCP fighting...
This is te server thread code

Complete server thread:
[code]
DWORD WINAPI tcpThread::serverthread_run(LPVOID lparam)
{

const int kBufferSize=1024;

sockaddr_in sock;
int porta=(int)lparam;

sock.sin_family=AF_INET; //Address family
sock.sin_addr.s_addr=ADDR_ANY; //IP address
sock.sin_port=htons((u_short)porta); //port to use

SOCKET serverSock=socket(AF_INET,SOCK_STREAM,0);

if(serverSock==INVALID_SOCKET)
{
int errorSock=WSAGetLastError();
MessageBox(NULL,"socket() error","Oh!",MB_OK);
return 0; //CTRL_INIT_ERROR;
}

int errorBind=bind(serverSock,(struct sockaddr*)&sock,sizeof(sock));

if(errorBind==SOCKET_ERROR)
{
int errorNew=WSAGetLastError();
MessageBox(NULL,"Bind() error nel server","Oh!",MB_OK);
return 0; //BIND_ERROR;
}

//Ciclo di ascolto
while(1)
{
listen(serverSock,1);
int nAddrSize = sizeof(sock);

SOCKET client = accept(serverSock, (sockaddr*)&sock, &nAddrSize);

if (client==INVALID_SOCKET) {

MessageBox(NULL,"Errore socket II","Oh!",MB_OK);
}

//rimbalzo dei pacchetti
char acReadBuffer[kBufferSize];
int nReadBytes;

do {
nReadBytes = recv(client, acReadBuffer, kBufferSize, 0);
if (nReadBytes > 0) {

int nSentBytes = 0;
while (nSentBytes < nReadBytes) {
int nTemp = send(client, acReadBuffer + nSentBytes, nReadBytes - nSentBytes, 0);

if (nTemp > 0) {
//numero dei bytes rispediti a ogni giro
nSentBytes += nTemp;
}

else if (nTemp == SOCKET_ERROR) {

MessageBox(NULL,"Errore socket nel rimbalzo dati","Oh!",MB_OK);
}
else {

MessageBox(NULL,"Connessione resettata nel rimbalzo dati","Oh!",MB_OK);
}

}

} else if (nReadBytes == SOCKET_ERROR) {

MessageBox(NULL,"Errore ricezione dati nel rimbalzo", "Oh!",MB_OK);

}

} while (nReadBytes != 0);

closesocket(client);
}

}
ZillionDollarSadist at 2007-11-9 13:58:21 >
# 11 Re: After a lot of TCP fighting...
set your port correctly in this line.
localSock.sin_port=htons((u_short)2003); //port to use
That was the first problem I found.

I was able to connect with the code you sent me.
ahoodin at 2007-11-9 13:59:31 >
# 12 Re: After a lot of TCP fighting...
You're right - it was a wrong port I was sending to! Grrrrr! :)
Now, what about gentle socket connection?
I think I need something on the client side, because I can't send twice in a row with no errors...
Thanks!
ZillionDollarSadist at 2007-11-9 14:00:30 >
# 13 Re: After a lot of TCP fighting...
Also, I can connect with the sockaddr_in structure declared inside the thread, but the old error strikes back when I pass a &sockaddr_in param to the client thread. Any suggestion?
Thanks.
ZillionDollarSadist at 2007-11-9 14:01:25 >
# 14 Re: After a lot of TCP fighting...
Yes ZillionDollaSadist!

After your client sends the data and recieve all the data you expect on the client, you must close your socket.

//MessageBox(NULL,"Risposta ok!","Oh!",MB_OK);
cout <<"Riposta ok!"<<endl;
closesocket(clientSock);

It worked for me! I was able to send the data and close the socket gracefully/consistantly.

You will need to come up with a scheme to get your own client and server to work. How will my server know how many bytes to receive. What will it send back, how will my client know how many bytes were received successfully? Etc.
Otherwise your just making an echoserver.

HTH,

ahoodin

*PS IF this helped dont forget to rate. Just click the scale icon and click approve.*
ahoodin at 2007-11-9 14:02:31 >
# 15 Re: After a lot of TCP fighting...
Yes ZillionDollaSadist!

After your client sends the data and recieve all the data you expect on the client, you must close your socket.

It worked for me! I was able to send the data and close the socket gracefully/consistantly.

It's all working now! Wow!
I close with shutdown and then closesocket. And following connections are all fine.

You will need to come up with a scheme to get your own client and server to work. How will my server know how many bytes to receive. What will it send back, how will my client know how many bytes were received successfully? Etc.
Otherwise your just making an echoserver.

The stuff I sent in fact was just a skeleton I have to build upon now. I'll have to decide something about packets now, right? :)
Thanks a lot.
ZillionDollarSadist at 2007-11-9 14:03:35 >
# 16 Re: After a lot of TCP fighting...
I have one more bizarre behavoir. This the complete client thread code:

DWORD WINAPI tcpThread::clientthread_run(LPVOID lparam)
{
//va fatto in modo da sincronizzarsi per bene con il server per mezzo
//di segnasli di ACK e similia.

const int kBufferSize=1408;
const char* kpcEchoMessage = "This is a test of the emergency data "
"transfer system. If this had been real a real emergency, we "
"would have sent this data out-of-band.";
const int kEchoMessageLen = strlen(kpcEchoMessage);
const int kShutdownDelay = 3;

tcpThread* thisClient=(tcpThread*) lparam;

//Client socket locale
sockaddr_in localSock;
localSock.sin_family=AF_INET; //Address family
localSock.sin_addr.s_addr=thisClient->clientSocket.sin_addr.s_addr;
localSock.sin_port=thisClient->clientSocket.sin_port;

//connectData* client=(connectData*)lparam;

//Connessione al server

SOCKET clientSock=socket(AF_INET, SOCK_STREAM, 0);

if (clientSock==INVALID_SOCKET) {MessageBox(NULL,"Creazione socket:una merda","Oh!",MB_OK);}

if (connect(clientSock, (sockaddr*)&localSock, sizeof(sockaddr_in)) == SOCKET_ERROR) {

clientSock = INVALID_SOCKET;
MessageBox(NULL,"Socket rancido nel client","Oh!",MB_OK);

}
//-------

//Manda stringa al server
int sentBytes=send(clientSock, kpcEchoMessage, kEchoMessageLen, 0);
if (sentBytes == SOCKET_ERROR) {

MessageBox(NULL,"Spedizione andata a male", "De'",MB_OK);

} else thisClient->tx_data=sentBytes;

//--------

//Ricevi risposta dal server
char acReadBuffer[kBufferSize];
int nTotalBytes = 0;

while (nTotalBytes < kEchoMessageLen) {

int nNewBytes = recv(clientSock, acReadBuffer + nTotalBytes,kBufferSize - nTotalBytes, 0);
if (nNewBytes == SOCKET_ERROR) {
return -1;
}

else if (nNewBytes == 0) {

MessageBox(NULL,"Connessione resettata dal piiir","Oh",MB_OK);
}

nTotalBytes += nNewBytes;

}


//Qui si controlla che i dati siano tutti a posto
if (strncmp(acReadBuffer, kpcEchoMessage, nTotalBytes) == 0) {
MessageBox(NULL,"Risposta ok!","Oh!",MB_OK);
thisClient->rx_data=nTotalBytes;
}

else {
MessageBox(NULL,"Qualcosa nei dati si e' sbombolato", "Oh!",MB_OK);
}

//--------

//Controllo errori vari
int nBytes;
if (nTotalBytes>0) {

if (nTotalBytes==kBufferSize) {

MessageBox(NULL,"Qualche troiaio, forse overflow", "Oh!",MB_OK);
}

} else if (nTotalBytes==0) {

MessageBox(NULL,"Connessione chiusa a cavolo","Oh!",MB_OK);

} else {

MessageBox(NULL,"Altri errori scassanti","Oh!",MB_OK);

}

//chiusura socket
shutdown(clientSock,1);
closesocket(clientSock);

}

This client thread method is part of class I created for implementing the server and client; I have to pass to the outside how many bytes have been sent and recieved, so I created two int members in the thread class (tx_data for sent data, rx_data for recieved data) whose values are given inside of the running thread, which takes a <i>this</i> pointer as argument. Then two functions return tx_data and rx_data to the outside.
Now, the test I made use a 136 bytes string, and If I control the values of tx_data and rx_data inside of the thread class, they're correct.
But when passed to the outside program, hte values go nuts (for example, one times I have 48 sent and 13 recieved, then 0 and -28769876, then...).
Any idea? It looks dreadful.
Thanks!
ZillionDollarSadist at 2007-11-9 14:04:29 >
# 17 Re: After a lot of TCP fighting...
Nevermind my last message, I figured it out by myself. Wow.
ZillionDollarSadist at 2007-11-9 14:05:27 >