I'm using the code below to send messages between the through the two programs.
It works, but I'm getting a lot of excess characters and I have no idea where they came from...
http://i56.tinypic.com/5by613.png
Server:
Code:#pragma comment(lib, "ws2_32")
#include <winsock2.h>
#include <iostream>
using namespace std;
int StartServerListening(unsigned short port);
void EndServer(int socket);
HANDLE Hthread; // Used to handle our threads
HANDLE Hmutex; // A mutex is bascially a memory spot we can lock so nothing writes to it as we read form it.. That could cause issues
FD_SET masterSet; // This basically is our list of sockets that we will lock and unlock with out mutexHandle
// A FD_SET has a few data members:
// - fd_count - the number of file descriptors in the set
// - fd_array - the array of file descriptors
// We can use these little macros to help edit the FD_SET
// - FD_SET(a socket, FD_SET to manipulate) - add a scoket to the set
// - FD_ZERO(FD_SET to manipulate) - zero a set
// - FD_CLR(a socket, FD_SET to manipulate) - remove a socket from the set
// - FD_ISSET(a socket, FD_SET to manipulate) - checks if the socket is already in the set
bool gQuitFlag = false;// A flag ill use to terminate the program if it goes terribly wrong
// AcceptThread() - a This function will accept ALL incomming connections Then add to the FD_SET list
void AcceptThread(int* serverSocket)
{
SetConsoleTitle(L"Server");
int mySocket = *serverSocket; // Copy my socket over to a local variable
for (;;)
{
unsigned int clientSocket = accept(mySocket, 0, 0); // Do a normal accept
if (clientSocket == SOCKET_ERROR)
{
gQuitFlag = true; // Quit this thread
return;
}
else
{
WaitForSingleObject(Hmutex, INFINITE);// Lock the mutex and wait for it
FD_SET(clientSocket, &masterSet);// Add this socket to the master set using FD_SET()
ReleaseMutex(Hmutex);// Unlock the mutex
cout << "client on " << clientSocket <<" connected.\n" << endl;// Let everyone know someone just joined
}
}
}
int main()
{
int serverSocket;
serverSocket = StartServerListening(7700);
if (serverSocket == -1)
{
return 1;
}
Hmutex = CreateMutex(NULL, false, NULL);// Create the mutex
if (Hmutex == NULL)
{
EndServer(serverSocket);
return 1;
}
int thread;// Create the thread
Hthread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)AcceptThread, &serverSocket, 0, (LPDWORD)&thread);
if (Hthread == NULL)
{
EndServer(serverSocket);
return 1;
}
Sleep(100);// Let the AcceptThread start up, cheap method, but oh well -.-;
FD_ZERO(&masterSet); // Always zero your sets before you use them, you know.. just incase...
for (;;)
{
if (gQuitFlag)
{
break;
}
WaitForSingleObject(Hmutex, INFINITE); // Lock the mutex
FD_SET TempSet = masterSet; // Make a temp location so we can unlock our mutex and let our accept thread run ASAP
ReleaseMutex(Hmutex); // Unlock the mutex
if (TempSet.fd_count == 0) // If a set is empty and we call form it, it returns a error, thats too much coding for me
{ // So we will simply check if there is anything in it, if so we will do something, else screw it -.-;
continue;
}
// select() has 5 member datas of use to us they are
// - the number of file descriptors
// - a FD_SET checks readability
// - a FD_SET checks for writeability
// - a FD_SET checks for errors
// - a wait time
timeval waitTime; // Set up our interval
waitTime.tv_sec = 0; // Set it to 0
waitTime.tv_usec = 0; // Set it to 0
int result = select(TempSet.fd_count, &TempSet, NULL, NULL, &waitTime); // Select a socket in out TempSet
if (result == 0) // Check for 0's agian
{
continue; // = Empty
}
if (result == SOCKET_ERROR)
{
continue;
}
for (unsigned int i = 0; i < TempSet.fd_count; i++)
{
unsigned int clientSocket = TempSet.fd_array[i];
int nBytes;
#define MAX_MESSAGE_SIZE 4096
char buffer[MAX_MESSAGE_SIZE];
unsigned long messageSize;
nBytes = recv(clientSocket, (char*)&messageSize, sizeof(messageSize), 0);
if (nBytes == SOCKET_ERROR)
{
int error = WSAGetLastError();// Main error you will get here is if the other client suddenly disconnects or loses power or something similar
if (error == WSAECONNRESET)
{
WaitForSingleObject(Hmutex, INFINITE); // Lock our mutex
FD_CLR(clientSocket, &masterSet); // Remove the socket from our master set
ReleaseMutex(Hmutex); // Unlock our mutex
closesocket(clientSocket); // Close the socket on our side so our computer cleans up properly
cout << "Server: Client on "<< clientSocket << " has Disconnected." << endl; // Tell everyone the person left
continue;
}
else
{
gQuitFlag = true;
break;
}
}
if (nBytes == 0) // Called if the user exits and calls closesocket() on THEIR side. They stops ending data, thus 0 bytes, ets jsut remove them from the set
{
WaitForSingleObject(Hmutex, INFINITE); // Lock our mutex
FD_CLR(clientSocket, &masterSet); // Remove the socket from our master set
ReleaseMutex(Hmutex); // Unlock our mutex
closesocket(clientSocket); // Close the socket on our side, so our computer cleans up properly
cout << "Server: Client on " << clientSocket << " has disconnected" << "\n";// Quick Message to the rest in the room
continue;// On to the next one!
}
messageSize = ntohl(messageSize);
nBytes = recv(clientSocket, buffer, messageSize, 0);
if (nBytes == SOCKET_ERROR)
{
cout << "Server: I failed the message sir!\n";
gQuitFlag = true;
break;
}
buffer[messageSize] = ' ';
cout << "Server: Client [" << clientSocket << "]: " << buffer << "\n";
}
}
EndServer(serverSocket);
cout << "Server: Press any key to shut me down....\n";
cin.get();
return 0;
}
int StartServerListening(unsigned short port)
{
int error;
WSAData wsaData;
if ((error = WSAStartup(MAKEWORD(2, 2), &wsaData)) == SOCKET_ERROR)
{
cout << "Server: Winsock is being a .......... Sir!\n";
return -1;
}
int mySocket = socket(AF_INET, SOCK_STREAM, 0);
if (mySocket == SOCKET_ERROR)
{
cout << "Server: ****ing Socket is stuck closed!\n";
return -1;
}
struct sockaddr_in server;
server.sin_family = AF_INET;
server.sin_port = htons(port);
server.sin_addr.s_addr = INADDR_ANY;
if (bind(mySocket, (sockaddr*)&server, sizeof(server)) == SOCKET_ERROR)
{
cout << "Server: Sorry Sir! My Bind Failed!\n";
closesocket(mySocket);
return -1;
}
if (listen(mySocket, 5) == SOCKET_ERROR)
{
cout << "Server: I failed to listen -.-;\n";
closesocket(mySocket);
return -1;
}
cout << "Server: Starting Up.. READY!\n";
return mySocket;
}
void EndServer(int socket)
{
WaitForSingleObject(Hthread, INFINITE);// Kill thread and handle
CloseHandle(Hthread);
CloseHandle(Hmutex);
closesocket(socket);
WSACleanup();
cout << "Server: Shuting down master.\n";
}
Client:
Code:#pragma comment(lib, "ws2_32")
int StartClient(unsigned short port, const char* serverName);
void EndClient(int clientSocket);
#include <winsock2.h>
#include <iostream>
using namespace std;
int main()
{
SetConsoleTitle(L"Client");
int mySocket;
mySocket = StartClient(7700, "localhost");
if (mySocket == -1)
{
EndClient(mySocket);
return 1;
}
int nBytes;
#define MAX_MESSAGE_SIZE 4096
char buffer[MAX_MESSAGE_SIZE];
cout << "Message to send (exit to exit) > ";
for (;;)
{
gets(buffer);
if (strcmp(buffer, "exit") == 0)
{
break;
}
unsigned long messageSize = strlen(buffer);
messageSize = htonl(messageSize);
if ((nBytes = send(mySocket, (char*)&messageSize, sizeof(messageSize), 0)) == SOCKET_ERROR)
{
cout << "Client: Error Sending.\n";
}
messageSize = ntohl(messageSize);
if ((nBytes = send(mySocket, buffer, messageSize, 0)) == SOCKET_ERROR)
{
cout << "Client: Error Sending.\n";
}
cout << "\n>";
}
EndClient(mySocket);
return 0;
}
int StartClient(unsigned short port, const char* serverName)
{
int error;
WSAData wsaData;
if ((error = WSAStartup(MAKEWORD(2, 2), &wsaData)) == SOCKET_ERROR)
{
cout << "Client: Error Connecting.\n";
return -1;
}
int mySocket = socket(AF_INET, SOCK_STREAM, 0);
if (mySocket == SOCKET_ERROR)
{
cout << "Client: Error Connecting.\n";
return -1;
}
struct hostent *host_entry;
if ((host_entry = gethostbyname(serverName)) == NULL)
{
cout << "Client: Eror Resolving Host.\n";
}
struct sockaddr_in server;
server.sin_family = AF_INET;
server.sin_port = htons(port);
server.sin_addr.s_addr = *(unsigned long*) host_entry->h_addr;
if (connect(mySocket, (sockaddr*)&server, sizeof(server)) == SOCKET_ERROR)
{
cout << "Client: Error Connecting.\n";
}
cout << "Client: Connection Successful.\n";
return mySocket;
}
void EndClient(int clientSocket)
{
closesocket(clientSocket);
WSACleanup();
}