I’m having trouble with a simple TCP socket with the connect() and read() function. This program works if I start the server first, and the client second. However, when I start the client first, it continues to try to connect to the server, then when I start the server, it connects but the subsequent read returns 0 bytes. This suggests that the server closed the socket, but the debug statements do not support this.
I’m trying to have the client continually trying to connect to the server on port 6380, then read data. If the connection is lost, the client will try to reconnect again. I have SO_REUSEADDR set for the sockets. Is there something else that I'm missing?
Source Code for Server
//***** SERVER *****
#include <iostream>
#include "SocketAdapter.h"
#include "SocketServer.h"
#include <errno.h>
#include <string.h>
unsigned char buffer[] = "123123123";
int main()
{
SocketAdapter socket;
SocketServer server(6380);
server.Start();
std::cout << "Wait for Connection" << std::endl;
server.WaitForConnection(socket);
std::cout << "Start to Send Data" << std::endl;
while(1)
{
std::cout << "Sending Data ";
int bytesSent = socket.Send(buffer, 10);
std::cout << "byteSent = " << bytesSent << std::endl;
if (bytesSent == -1)
{
std::cout << "Errno (" << errno << ") - " << strerror(errno) << std::endl;
}
sleep(1);
}//end while
std::cout &l开发者_如何学Pythont;< "Ending Server" << std::endl;
socket.Close();
return 0;
}
Source Code for Client
// ***** SIMPLE CLIENT ******
#include <iostream>
#include "SocketAdapter.h"
#include "SocketClient.h"
#include <string.h>
#include <errno.h>
int main()
{
SocketAdapter socket;
SocketClient client(6380, "127.0.0.1");
unsigned char buffer[1024];
while(1)
{
client.Start();
//Loop till we connect to Server
while( !client.Connect(socket) )
{
std::cout << "Trying to connect to server." << std::endl;
sleep(1);
}
std::cout << "Connected to Server" << std::endl;
//Read till we get a timeout
while(1)
{
int bytesRead = socket.Recv(buffer, 10,2000);
if (bytesRead != 10)
{
std::cout << " Failed to Read" << std::endl;
std::cout << " bytesRead = " << bytesRead << std::endl;
std::cout << " Errno (" << errno << ") - "
<< strerror(errno) << std::endl;
break;
}
std::cout << "buffer = " << buffer << std::endl;
usleep(250000);
}
std::cout << "Something went wrong, restart" << std::endl;
}
return 0;
}
OUTPUT OF SERVER
./Server
Wait for Connection
Start to Send Data
Sending Data byteSent = 10
OUTPUT OF CLIENT
./Client
Trying to connect to server.
Trying to connect to server.
Connected to Server
Failed to Read
bytesRead = 0
Errno (107) - Transport endpoint is not connected
Something went wrong, restart
Close Socket
Close Socket File Descriptor
Connected to Server
Trying to Recv on a closed socket
Return Value = -1
Errno = Connection reset by peer
Failed to Read
bytesRead = -3
Errno (104) - Connection reset by peer
Something went wrong, restart
Close Socket
Close Socket File Descriptor
Socket cannot shutdown!
Return Value = -1
Errno = Transport endpoint is not connected
Trying to connect to server.
Close Socket
Close Socket File Descriptor
Socket cannot shutdown!
Return Value = -1
Errno = Transport endpoint is not connected
A return of 0 read bytes from a socket is perfectly legal. This only means you have to wait and try again.
For instance look at this read_data() function. It checks if number of read bytes are > 0
, then it stores them. It checks if number of read bytes are < 0
, then it is an error.
The 0 case is not really a great success, of course, but not a failure. Just try again. I did not analyze your code in great detail, so there may be something else, but this is an important error often made. (Also, what is in those classes not shown?)
What you could look into is non-blocking sockets. Also see the FAQ for how to tell if a socket is closed on the other end. And maybe consider detecting transfer completion explicitly by sending and end-of-file or marker.
精彩评论