|
C++ Simple Client Socket Program Example
Create a new CLR console application project and you might want to use SimpleSocketClientCP as the name.
|
Add the following code.
// SimpleSocketClientCP.cpp : main project file. /// <summary> /// This is a simple TCP and UDP based client. /// </summary>
#include "stdafx.h"
using namespace System; using namespace System::Net; using namespace System::Net::Sockets;
/// <summary> /// This routine repeatedly copies a string message into a byte array until filled. /// </summary> /// <param name="dataBuffer">Byte buffer to fill with string message</param> /// <param name="message">String message to copy</param> static public void FormatBuffer(array<Byte>^ dataBuffer, String^ message) { array<Byte>^ byteMessage = Text::Encoding::ASCII->GetBytes(message); int index = 0;
// First convert the string to bytes and then copy into send buffer while (index < dataBuffer->Length) { for (int j = 0; j < byteMessage->Length; j++) { dataBuffer[index] = byteMessage[j]; index++;
// Make sure we don't go past the send buffer length if (index >= dataBuffer->Length) { break; } } } Console::Write(message + "\n"); }
/// <summary> /// Prints simple usage information. /// </summary> static public void usage() { Console::WriteLine("usage: Executable_file_name [-c] [-n server] [-p port] [-m message]"); Console::WriteLine(" [-t tcp|udp] [-x size]"); Console::WriteLine("Available options:"); Console::WriteLine(" -c If UDP connect the socket before sending"); Console::WriteLine(" -n server Server name or address to connect/send to"); Console::WriteLine(" -p port Port number to connect/send to"); Console::WriteLine(" -m message String message to format in request buffer"); Console::WriteLine(" -t tcp|udp Indicates to use either the TCP or UDP protocol"); Console::WriteLine(" -x size Size of send and receive buffers"); }
/// <param name="args">Command line arguments</param> int main(array<System::String ^> ^args) { // Initialize to the default values SocketType sockType = SocketType::Stream; ProtocolType sockProtocol = ProtocolType::Tcp; String^ remoteName = "localhost"; String^ textMessage = "Client: This is a test message from client!"; bool udpConnect = false; int remotePort = 5150, bufferSize = 4096;
if(args->Length != 0) { // Parse the command line for (int i = 0; i < args->Length; i++) { try { if ((args[i][0] == '-') || (args[i][0] == '/')) { switch (Char::ToLower(args[i][1])) { case 'c': // "Connect" the UDP socket to the destination udpConnect = true; break; case 'n': // Destination address to connect to or send to remoteName = args[++i]; break; case 'm': // Text message to put into the send buffer textMessage = args[++i]; break; case 'p': // Port number for the destination remotePort = Convert::ToInt32(args[++i]); break; case 't': // Specified TCP or UDP i++; if (String::Compare(args[i], "tcp", true) == 0) { sockType = SocketType::Stream; sockProtocol = ProtocolType::Tcp; } else if (String::Compare(args[i], "udp", true) == 0) { sockType = SocketType::Dgram; sockProtocol = ProtocolType::Udp; } else { usage(); return 0; } break; case 'x': // Size of the send and receive buffers bufferSize = Convert::ToInt32(args[++i]); break; default: usage(); return 0; } } } catch(Exception^ err) { Console::WriteLine("Error: {0}.", err->Message); usage(); return 0; } } } else { usage(); return 0; }
Socket^ clientSocket = nullptr; IPHostEntry^ resolvedHost = nullptr; IPEndPoint^ destination = nullptr;
// Setting-up buffers Console::WriteLine("Client: Setting up receive and send buffers..."); array<Byte>^ sendBuffer = gcnew array<Byte>(bufferSize); array<Byte>^ recvBuffer = gcnew array<Byte>(bufferSize); int rc;
// Format the string message into the send buffer Console::WriteLine("Client: Formatting the string message into the send buffer..."); FormatBuffer(sendBuffer, textMessage);
try { // Try to resolve the remote host name or address Console::WriteLine("Client: Resolving the remote host name or address..."); resolvedHost = Dns::GetHostEntry(remoteName); Console::WriteLine("Client: GetHostEntry() is OK...");
// Try each address returned Console::WriteLine("Client: Trying each available address returned & creating socket..."); for each (IPAddress^ addr in resolvedHost->AddressList) { // Create a socket corresponding to the address family of the resolved address clientSocket = gcnew Socket(addr->AddressFamily, sockType, sockProtocol); Console::WriteLine("Client: Socket() is OK..."); try { // Create the endpoint that describes the destination Console::WriteLine("Client: Creating the destination endpoint..."); destination = gcnew IPEndPoint(addr, remotePort); Console::WriteLine("Client: IPEndPoint() is OK. IP Address: {0}, server port: {1}", addr, remotePort);
if ((sockProtocol == ProtocolType::Udp) && (udpConnect == false)) { Console::WriteLine("Client: UDP - Destination address is: {0}", destination); break; } else { Console::WriteLine("Client: TCP - Attempting connection to: {0}", destination); } clientSocket->Connect(destination); Console::WriteLine("Client: Connect() is OK..."); break; } catch (SocketException^ err) { // Connect failed so close the socket and try the next address clientSocket->Close(); Console::WriteLine("Client: Client socket closed. Error code: " + err->ErrorCode); Console::WriteLine("Client: " + err->Message); clientSocket = nullptr; continue; } }
// Make sure we have a valid socket before trying to use it if ((clientSocket != nullptr) && (destination != nullptr)) { try { // Send the request to the server if ((sockProtocol == ProtocolType::Udp) && (udpConnect == false)) { clientSocket->SendTo(sendBuffer, destination); Console::WriteLine("Client: UDP - SendTo() is OK..."); } else { rc = clientSocket->Send(sendBuffer); Console::WriteLine("Client: TCP - send() is OK..."); Console::WriteLine("Client: Sent request of {0} bytes", rc);
// For TCP, shutdown sending on our side since the client won't send any more data if (sockProtocol == ProtocolType::Tcp) { clientSocket->Shutdown(SocketShutdown::Send); Console::WriteLine("Client: Shutdown() is OK..."); } }
// Receive data in a loop until the server closes the connection. For // TCP this occurs when the server performs a shutdown or closes // the socket. For UDP, we'll know to exit when the remote host // sends a zero byte datagram. while (true) { if ((sockProtocol == ProtocolType::Tcp) || (udpConnect == true)) { rc = clientSocket->Receive(recvBuffer); Console::WriteLine("Client: Receive() is OK..."); Console::WriteLine("Client: Read {0} bytes", rc); } else { IPEndPoint^ fromEndPoint = gcnew IPEndPoint(destination->Address, 0); Console::WriteLine("Client: IPEndPoint() is OK..."); EndPoint^ castFromEndPoint = (EndPoint^)fromEndPoint; rc = clientSocket->ReceiveFrom(recvBuffer, castFromEndPoint); Console::WriteLine("Client: ReceiveFrom() is OK..."); fromEndPoint = (IPEndPoint^)castFromEndPoint; Console::WriteLine("Client: Read {0} bytes from {1}", rc, fromEndPoint); }
// Exit loop if server indicates shutdown if (rc == 0) { clientSocket->Close(); Console::WriteLine("Client: Close() is OK..."); break; } }
} catch (SocketException^ err) { Console::WriteLine("Client: Error occurred while sending or receiving data."); Console::WriteLine(" Error: {0}, code: {1}", err->Message, err->ErrorCode); } } else { Console::WriteLine("Client: Unable to establish connection to server!"); } } catch (SocketException^ err) { Console::WriteLine("Client: Socket error occurred: {0}, code: {1}", err->Message, err->ErrorCode); } return 0; } |
Build and run the project. The following are the output samples when the executable run at the command prompt.
Next, let test this client program with the server program that previously created. Firstly run the server program. The server is listening for client connection.
Then, run the client program using the same protocol (TCP) and connecting to the port that the server is listening. The following is the output sample.
|
The following is the receiver/server output screenshot when the communication was completed. You may want to test this program on real network.
The following output samples show the UDP protocol.