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 
00034 namespace sf
00035 {
00039 SocketTCP::SocketTCP() :
00040 mySocket(socket(PF_INET, SOCK_STREAM, 0))
00041 {
00042     // To avoid the "Address already in use" error message when trying to bind to the same port
00043     char Yes = 1;
00044     if (setsockopt(mySocket, SOL_SOCKET, SO_REUSEADDR, &Yes, sizeof(int)) == -1)
00045     {
00046         std::cerr << "Failed to set socket option \"reuse address\" ; "
00047                   << "binding to a same port may fail if too fast" << std::endl;
00048     }
00049 }
00050 
00051 
00055 bool SocketTCP::Connect(unsigned short Port, const IPAddress& HostAddress)
00056 {
00057     // First check that socket is valid
00058     if (mySocket == INVALID_SOCKET)
00059         return false;
00060 
00061     // Build the host address
00062     sockaddr_in SockAddr;
00063     memset(SockAddr.sin_zero, 0, sizeof(SockAddr.sin_zero));
00064     SockAddr.sin_addr.s_addr = inet_addr(HostAddress.ToString().c_str());
00065     SockAddr.sin_family      = AF_INET;
00066     SockAddr.sin_port        = htons(Port);
00067 
00068     // Connect
00069     if (connect(mySocket, reinterpret_cast<sockaddr*>(&SockAddr), sizeof(SockAddr)) == -1)
00070     {
00071         // Error...
00072         std::cerr << "Failed to connect socket to host " << HostAddress << std::endl;
00073         return false;
00074     }
00075 
00076     return true;
00077 }
00078 
00079 
00083 bool SocketTCP::Listen(unsigned short Port)
00084 {
00085     // First check that socket is valid
00086     if (mySocket == INVALID_SOCKET)
00087         return false;
00088 
00089     // Build the address
00090     sockaddr_in SockAddr;
00091     memset(SockAddr.sin_zero, 0, sizeof(SockAddr.sin_zero));
00092     SockAddr.sin_addr.s_addr = htonl(INADDR_ANY);
00093     SockAddr.sin_family      = AF_INET;
00094     SockAddr.sin_port        = htons(Port);
00095 
00096     // Bind the socket to the specified port
00097     if (bind(mySocket, reinterpret_cast<sockaddr*>(&SockAddr), sizeof(SockAddr)) == -1)
00098     {
00099         // Not likely to happen, but...
00100         std::cerr << "Failed to bind socket to port " << Port << std::endl;
00101         return false;
00102     }
00103 
00104     // Listen to the bound port
00105     if (listen(mySocket, 0) == -1)
00106     {
00107         // Oops, socket is deaf
00108         std::cerr << "Failed to listen to port " << Port << std::endl;
00109         return false;
00110     }
00111 
00112     return true;
00113 }
00114 
00115 
00121 SocketTCP SocketTCP::Accept(IPAddress* Address)
00122 {
00123     // Address that will be filled with client informations
00124     sockaddr_in ClientAddress;
00125     socklen_t Length = sizeof(ClientAddress);
00126 
00127     // Accept a new connection
00128     SocketTCP ClientSocket = accept(mySocket, reinterpret_cast<sockaddr*>(&ClientAddress), &Length);
00129 
00130     // Check errors
00131     if (ClientSocket.mySocket == INVALID_SOCKET)
00132     {
00133         std::cerr << "Failed to accept socket connection" << std::endl;
00134         return ClientSocket;
00135     }
00136 
00137     // Fill address if requested
00138     if (Address)
00139         *Address = IPAddress(inet_ntoa(ClientAddress.sin_addr));
00140 
00141     return ClientSocket;
00142 }
00143 
00144 
00148 bool SocketTCP::Send(const char* Data, std::size_t Size)
00149 {
00150     // First check that socket is valid
00151     if (mySocket == INVALID_SOCKET)
00152         return false;
00153 
00154     // Check parameters
00155     if (Data && Size)
00156     {
00157         // Loop until every byte has been sent
00158         int Sent = 0;
00159         int SizeToSend = static_cast<int>(Size);
00160         for (int Length = 0; Length < SizeToSend; Length += Sent)
00161         {
00162             // Send a chunk of data
00163             Sent = send(mySocket, Data + Length, SizeToSend - Length, 0);
00164 
00165             // Check if connection is still alive
00166             if (Sent <= 0)
00167                 return false;
00168         }
00169     }
00170     else
00171     {
00172         // Error... (don't return false, we're still connected !)
00173         std::cerr << "Cannot send data over the network (invalid parameters)" << std::endl;
00174     }
00175 
00176     return true;
00177 }
00178 
00179 
00185 bool SocketTCP::Receive(char* Data, std::size_t MaxSize, std::size_t& SizeReceived)
00186 {
00187     // First clear the size received
00188     SizeReceived = 0;
00189 
00190     // Check that socket is valid
00191     if (mySocket == INVALID_SOCKET)
00192         return false;
00193 
00194     // Check parameters
00195     if (Data && MaxSize)
00196     {
00197         // Receive a chunk of bytes
00198         int Received = recv(mySocket, Data, static_cast<int>(MaxSize), 0);
00199 
00200         // Check the number of bytes received
00201         if (Received > 0)
00202             SizeReceived = static_cast<std::size_t>(Received);
00203         else
00204             return false;
00205     }
00206     else
00207     {
00208         // Error... (don't return false, we're still connected !)
00209         std::cerr << "Cannot receive data from the network (invalid parameters)" << std::endl;
00210     }
00211 
00212     return true;
00213 }
00214 
00215 
00219 bool SocketTCP::Send(Packet& PacketToSend)
00220 {
00221     // Let the packet do custom stuff before sending it
00222     PacketToSend.OnSend();
00223 
00224     // First send the packet size
00225     Uint32 PacketSize = htonl(PacketToSend.GetDataSize());
00226     if (!Send(reinterpret_cast<const char*>(&PacketSize), sizeof(PacketSize)))
00227         return false;
00228 
00229     // Send the packet data
00230     if (!Send(PacketToSend.GetData(), PacketToSend.GetDataSize()))
00231         return false;
00232 
00233     return true;
00234 }
00235 
00236 
00242 bool SocketTCP::Receive(Packet& PacketToReceive)
00243 {
00244     // We start by getting the size of the incoming packet
00245     std::size_t Received   = 0;
00246     Uint32      PacketSize = 0;
00247     if (!Receive(reinterpret_cast<char*>(&PacketSize), sizeof(PacketSize), Received))
00248         return false;
00249     PacketSize = ntohl(PacketSize);
00250 
00251     // Clear the packet
00252     PacketToReceive.Clear();
00253 
00254     // Then loop until we receive all the packet data
00255     char Buffer[1024];
00256     while (PacketToReceive.GetDataSize() < PacketSize)
00257     {
00258         // Receive a chunk of data
00259         if (!Receive(Buffer, sizeof(Buffer), Received))
00260             return false;
00261 
00262         // Append it into the packet
00263         PacketToReceive.Append(Buffer, Received);
00264     }
00265 
00266     // Let the packet do custom stuff after data reception
00267     PacketToReceive.OnReceive();
00268 
00269     return true;
00270 }
00271 
00272 
00276 bool SocketTCP::Close()
00277 {
00278     if (priv::close(mySocket) == -1)
00279     {
00280         std::cerr << "Failed to close socket" << std::endl;
00281         return false;
00282     }
00283 
00284     return true;
00285 }
00286 
00287 
00291 bool SocketTCP::operator ==(const SocketTCP& Other) const
00292 {
00293     return mySocket == Other.mySocket;
00294 }
00295 
00296 
00300 bool SocketTCP::operator !=(const SocketTCP& Other) const
00301 {
00302     return mySocket != Other.mySocket;
00303 }
00304 
00305 
00311 bool SocketTCP::operator <(const SocketTCP& Other) const
00312 {
00313     return mySocket < Other.mySocket;
00314 }
00315 
00316 
00321 SocketTCP::SocketTCP(priv::SocketType Descriptor) :
00322 mySocket(Descriptor)
00323 {
00324 
00325 }
00326 
00327 } // namespace sf