SocketTCP.cpp

00001 
00002 //
00003 // SFML - Simple and Fast Multimedia Library
00004 // Copyright (C) 2007 Laurent Gomila (laurent.gom@gmail.com)
00005 //
00006 // This software is provided 'as-is', without any express or implied warranty.
00007 // In no event will the authors be held liable for any damages arising from the use of this software.
00008 //
00009 // Permission is granted to anyone to use this software for any purpose,
00010 // including commercial applications, and to alter it and redistribute it freely,
00011 // subject to the following restrictions:
00012 //
00013 // 1. The origin of this software must not be misrepresented;
00014 //    you must not claim that you wrote the original software.
00015 //    If you use this software in a product, an acknowledgment
00016 //    in the product documentation would be appreciated but is not required.
00017 //
00018 // 2. Altered source versions must be plainly marked as such,
00019 //    and must not be misrepresented as being the original software.
00020 //
00021 // 3. This notice may not be removed or altered from any source distribution.
00022 //
00024 
00026 // Headers
00028 #include <SFML/Network/SocketTCP.hpp>
00029 #include <SFML/Network/IPAddress.hpp>
00030 #include <SFML/Network/Packet.hpp>
00031 #include <iostream>
00032 
00033 
00037 sfSocketTCP::sfSocketTCP() :
00038 mySocket(socket(PF_INET, SOCK_STREAM, 0))
00039 {
00040     // To avoid the "Address already in use" error message when trying to bind to the same port
00041     char Yes = 1;
00042     if (setsockopt(mySocket, SOL_SOCKET, SO_REUSEADDR, &Yes, sizeof(int)) == -1)
00043     {
00044         std::cerr << "Failed to set socket option \"reuse address\" ; "
00045                   << "binding to a same port may fail if too fast" << std::endl;
00046     }
00047 }
00048 
00049 
00053 bool sfSocketTCP::Connect(unsigned short Port, const sfIPAddress& HostAddress)
00054 {
00055     // First check that socket is valid
00056     if (mySocket == INVALID_SOCKET)
00057         return false;
00058 
00059     // Build the host address
00060     sockaddr_in SockAddr;
00061     memset(SockAddr.sin_zero, 0, sizeof(SockAddr.sin_zero));
00062     SockAddr.sin_addr.s_addr = inet_addr(HostAddress.ToString().c_str());
00063     SockAddr.sin_family      = AF_INET;
00064     SockAddr.sin_port        = htons(Port);
00065 
00066     // Connect
00067     if (connect(mySocket, reinterpret_cast<sockaddr*>(&SockAddr), sizeof(SockAddr)) == -1)
00068     {
00069         // Error...
00070         std::cerr << "Failed to connect socket to host " << HostAddress << std::endl;
00071         return false;
00072     }
00073 
00074     return true;
00075 }
00076 
00077 
00081 bool sfSocketTCP::Listen(unsigned short Port)
00082 {
00083     // First check that socket is valid
00084     if (mySocket == INVALID_SOCKET)
00085         return false;
00086 
00087     // Build the address
00088     sockaddr_in SockAddr;
00089     memset(SockAddr.sin_zero, 0, sizeof(SockAddr.sin_zero));
00090     SockAddr.sin_addr.s_addr = htonl(INADDR_ANY);
00091     SockAddr.sin_family      = AF_INET;
00092     SockAddr.sin_port        = htons(Port);
00093 
00094     // Bind the socket to the specified port
00095     if (bind(mySocket, reinterpret_cast<sockaddr*>(&SockAddr), sizeof(SockAddr)) == -1)
00096     {
00097         // Not likely to happen, but...
00098         std::cerr << "Failed to bind socket to port " << Port << std::endl;
00099         return false;
00100     }
00101 
00102     // Listen to the bound port
00103     if (listen(mySocket, 0) == -1)
00104     {
00105         // Oops, socket is deaf
00106         std::cerr << "Failed to listen to port " << Port << std::endl;
00107         return false;
00108     }
00109 
00110     return true;
00111 }
00112 
00113 
00119 sfSocketTCP sfSocketTCP::Accept(sfIPAddress* Address)
00120 {
00121     // Address that will be filled with client informations
00122     sockaddr_in ClientAddress;
00123     socklen_t Length = sizeof(ClientAddress);
00124 
00125     // Accept a new connection
00126     sfSocketTCP ClientSocket = accept(mySocket, reinterpret_cast<sockaddr*>(&ClientAddress), &Length);
00127 
00128     // Check errors
00129     if (ClientSocket.mySocket == INVALID_SOCKET)
00130     {
00131         std::cerr << "Failed to accept socket connection" << std::endl;
00132         return ClientSocket;
00133     }
00134 
00135     // Fill address if requested
00136     if (Address)
00137         *Address = sfIPAddress(inet_ntoa(ClientAddress.sin_addr));
00138 
00139     return ClientSocket;
00140 }
00141 
00142 
00146 bool sfSocketTCP::Send(const char* Data, std::size_t Size)
00147 {
00148     // First check that socket is valid
00149     if (mySocket == INVALID_SOCKET)
00150         return false;
00151 
00152     // Check parameters
00153     if (Data && Size)
00154     {
00155         // Loop until every byte has been sent
00156         int Sent = 0;
00157         int SizeToSend = static_cast<int>(Size);
00158         for (int Length = 0; Length < SizeToSend; Length += Sent)
00159         {
00160             // Send a chunk of data
00161             Sent = send(mySocket, Data + Length, SizeToSend - Length, 0);
00162 
00163             // Check if connection is still alive
00164             if (Sent <= 0)
00165                 return false;
00166         }
00167     }
00168     else
00169     {
00170         // Error... (don't return false, we're still connected !)
00171         std::cerr << "Cannot send data over the network (invalid parameters)" << std::endl;
00172     }
00173 
00174     return true;
00175 }
00176 
00177 
00183 bool sfSocketTCP::Receive(char* Data, std::size_t MaxSize, std::size_t& SizeReceived)
00184 {
00185     // First clear the size received
00186     SizeReceived = 0;
00187 
00188     // Check that socket is valid
00189     if (mySocket == INVALID_SOCKET)
00190         return false;
00191 
00192     // Check parameters
00193     if (Data && MaxSize)
00194     {
00195         // Receive a chunk of bytes
00196         int Received = recv(mySocket, Data, static_cast<int>(MaxSize), 0);
00197 
00198         // Check the number of bytes received
00199         if (Received > 0)
00200             SizeReceived = static_cast<std::size_t>(Received);
00201         else
00202             return false;
00203     }
00204     else
00205     {
00206         // Error... (don't return false, we're still connected !)
00207         std::cerr << "Cannot receive data from the network (invalid parameters)" << std::endl;
00208     }
00209 
00210     return true;
00211 }
00212 
00213 
00217 bool sfSocketTCP::Send(sfPacket& Packet)
00218 {
00219     // Let the packet do custom stuff before sending it
00220     Packet.OnSend();
00221 
00222     // First send the packet size
00223     sfUint32 PacketSize = htonl(Packet.GetDataSize());
00224     if (!Send(reinterpret_cast<const char*>(&PacketSize), sizeof(PacketSize)))
00225         return false;
00226 
00227     // Send the packet data
00228     if (!Send(Packet.GetData(), Packet.GetDataSize()))
00229         return false;
00230 
00231     return true;
00232 }
00233 
00234 
00240 bool sfSocketTCP::Receive(sfPacket& Packet)
00241 {
00242     // We start by getting the size of the incoming packet
00243     std::size_t Received   = 0;
00244     sfUint32    PacketSize = 0;
00245     if (!Receive(reinterpret_cast<char*>(&PacketSize), sizeof(PacketSize), Received))
00246         return false;
00247     PacketSize = ntohl(PacketSize);
00248 
00249     // Clear the packet
00250     Packet.Clear();
00251 
00252     // Then loop until we receive all the packet data
00253     char Buffer[1024];
00254     while (Packet.GetDataSize() < PacketSize)
00255     {
00256         // Receive a chunk of data
00257         if (!Receive(Buffer, sizeof(Buffer), Received))
00258             return false;
00259 
00260         // Append it into the packet
00261         Packet.Append(Buffer, Received);
00262     }
00263 
00264     // Let the packet do custom stuff after data reception
00265     Packet.OnReceive();
00266 
00267     return true;
00268 }
00269 
00270 
00274 bool sfSocketTCP::Close()
00275 {
00276     if (sf_private::close(mySocket) == -1)
00277     {
00278         std::cerr << "Failed to close socket" << std::endl;
00279         return false;
00280     }
00281 
00282     return true;
00283 }
00284 
00285 
00289 bool sfSocketTCP::operator ==(const sfSocketTCP& Other) const
00290 {
00291     return mySocket == Other.mySocket;
00292 }
00293 
00294 
00298 bool sfSocketTCP::operator !=(const sfSocketTCP& Other) const
00299 {
00300     return mySocket != Other.mySocket;
00301 }
00302 
00303 
00309 bool sfSocketTCP::operator <(const sfSocketTCP& Other) const
00310 {
00311     return mySocket < Other.mySocket;
00312 }
00313 
00314 
00319 sfSocketTCP::sfSocketTCP(sf_private::sfSocketType Descriptor) :
00320 mySocket(Descriptor)
00321 {
00322 
00323 }