Original Post
hi there, I have look at multicasting and need some help to split this up to one server and client that client sends data to server then the server sends to all clients that is connected to it, now its a (client,server in one) maybe I sounds stupid but im not good in network programming only whant to know how it works and so on. I hope that anyone can help split it up and someone have time for it, I will be grateful about it.
// Headers
#include <windows.h>
#include <winsock.h>
#include <stdio.h>
#include <conio.h>
//////////////////////////////////////////////////////////////////////////////////////////////////////
// Libraries: automatically link with winsock
#pragma comment(lib, "wsock32.lib")
//////////////////////////////////////////////////////////////////////////////////////////////////////
// Address definitions to be used in the multicast() function
#define MULTICAST_GROUP_IP "234.100.110.120"
#define DEFAULT_PORT 15
#define DEFAULT_TTL 2
#define STRING_LENGTH 100
//////////////////////////////////////////////////////////////////////////////////////////////////////
// Bread&butter error reporting
void PrintWinsockError()
{
LPVOID lpMsgBuf;
int iError = WSAGetLastError();
if(FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, 0, iError, 0, (LPTSTR)&lpMsgBuf, 0, 0))
{
cprintf("WSAGetLastError %d: %s", iError, lpMsgBuf);
LocalFree(lpMsgBuf);
}
else
{
cprintf("WSAGetLastError %d", iError);
}
}
//////////////////////////////////////////////////////////////////////////////////////////////////////
// Address-to-ip resolution
int iResolve(SOCKADDR_IN &addrResolve, char *cHost, UINT uiPort, UINT uiInterface)
{
struct in_addr iaHost; // Used to resolve IP and connect
LPHOSTENT lpHost; // Used to connect
unsigned int iIndex;
iaHost.s_addr = inet_addr((LPCSTR)cHost); // Check if this syntax is consistent with IP address
if(iaHost.s_addr == INADDR_NONE) // If not IP, must be hostname string
{
lpHost = gethostbyname(cHost); // Get host structure by host name
if(lpHost == NULL)return false; // Whoops! Unresolved hostname!
}
else // This is an IP so just get structure by address
{
lpHost = gethostbyaddr((LPCSTR)&iaHost, sizeof(struct in_addr), AF_INET); // Get host structure by address
if(lpHost == NULL)return false; // Whoops! Unresolved host IP!
}
for(iIndex = 0; iIndex < uiInterface; iIndex++)
if(!lpHost->h_addr_list[iIndex])
return false;
if(!lpHost->h_addr_list[uiInterface])
return false;
memset(&addrResolve, NULL, sizeof(addrResolve));
addrResolve.sin_family = AF_INET; // We only use internet addresses
addrResolve.sin_addr = *((LPIN_ADDR)lpHost->h_addr_list[uiInterface]); // The remote IP
addrResolve.sin_port = htons(uiPort); // The remote port
// Okays
return true;
}
//////////////////////////////////////////////////////////////////////////////////////////////////////
// Work out which ip comes first on this machine, or nth ip if iInterface is specified
bool bGetNetworkInterface(IN_ADDR ∈_addrLocal, unsigned int uiInterface = 0)
{
char cLocalHostName[MAX_PATH];
gethostname(cLocalHostName, sizeof(cLocalHostName));
SOCKADDR_IN addrLocal;
if(!iResolve(addrLocal, cLocalHostName, 0, uiInterface))
return false;
in_addrLocal = addrLocal.sin_addr;
return true;
}
//////////////////////////////////////////////////////////////////////////////////////////////////////
// Function to associate a socket with a multicast group
bool bJoinMulticastGroup(SOCKET UDP_Socket, char *cMulticastGroup)
{
// Used to set multicast TTL
char cTTL = DEFAULT_TTL;
// Set the multicast ttl
int iRet = setsockopt(UDP_Socket, IPPROTO_IP, IP_MULTICAST_TTL, (char *)&cTTL, sizeof(cTTL));
if(iRet == SOCKET_ERROR)
{
cprintf("Failed to set multicast ttl\r\n");
PrintWinsockError();
return false;
}
// Add socket to be a member of the multicast group
struct ip_mreq ipmr;
ipmr.imr_multiaddr.s_addr = inet_addr(cMulticastGroup);
bGetNetworkInterface(ipmr.imr_interface); // Does the job of... ipmr.imr_interface.s_addr = inet_addr("ip");
iRet = setsockopt(UDP_Socket, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char *)&ipmr, sizeof(ipmr));
if(iRet == SOCKET_ERROR)
{
cprintf("Failed to add multicast membership\r\n");
PrintWinsockError();
return false;
}
// Set the local interface from which multicast is to be transmitted
IN_ADDR inLocal;
bGetNetworkInterface(inLocal); // Does the job of inLocal = inet_addr("ip");
setsockopt(UDP_Socket, IPPROTO_IP, IP_MULTICAST_IF, (char *)&inLocal, sizeof(inLocal));
if(iRet == SOCKET_ERROR)
{
cprintf("Failed to set multicast interface\r\n");
PrintWinsockError();
return false;
}
return true;
}
//////////////////////////////////////////////////////////////////////////////////////////////////////
// Function that receives UDP packets (not just multicast ones)
bool bReceiveMulticast(SOCKET UDP_Socket, char *cMulticastGroup)
{
// Used to identify where the packet came from
SOCKADDR_IN addrFrom;
// String to hold the packet data
char cData[STRING_LENGTH];
// Holds status of incoming packet queue
ULONG ulQueue[1];
// Tracks if any packets are received
bool bGotPacket = false;
while(true)
{
// Did a packet come through?
*ulQueue = NULL; // Reset incoming packet status
if(ioctlsocket(UDP_Socket, FIONREAD, (ULONG FAR *)ulQueue)) // Ask the socket how many packets are waiting
{
cprintf("ioctlsocket failed\r\n");
PrintWinsockError();
return false;
}
// No packets waiting?
if(!*ulQueue)
break;
// Receive the packet
int size = sizeof(addrFrom);
int iRet = recvfrom(UDP_Socket, (char *)cData, sizeof(cData) - 1, 0, (struct sockaddr*)&addrFrom, &size);
if(iRet == SOCKET_ERROR)
{
cprintf("Packet arrived, but failed to be received\r\n");
PrintWinsockError();
return false;
}
// Terminate packet so we can display it as a string
cData[iRet] = 0;
// Print the contents of the packet
cprintf("Received packet from %s: \"%s\"\r\n", inet_ntoa(addrFrom.sin_addr), cData);
bGotPacket = true;
}
// If no packets received, inform the user
if(!bGotPacket)
cprintf("No packets received\r\n");
return true;
}
//////////////////////////////////////////////////////////////////////////////////////////////////////
// Function that sends a multicast
bool bSendMulticast(SOCKET UDP_Socket, char *cMulticastGroup)
{
// Used to track return values of functions
int iRet;
// Where the packet will be heading
SOCKADDR_IN addrDest;
memset(&addrDest, 0, sizeof(addrDest));
// String to hold the packet data
char cData[STRING_LENGTH];
// Destination IP Address
addrDest.sin_family = AF_INET;
addrDest.sin_port = htons(DEFAULT_PORT);
addrDest.sin_addr.s_addr = inet_addr(cMulticastGroup);
// Data to send
memset(cData, 0, sizeof(cData));
wsprintf((char *)cData, "test");
// Send to MULTICAST
iRet = sendto(UDP_Socket, (char *)cData, (int)strlen(cData), 0, (struct sockaddr*)&addrDest, sizeof(addrDest));
if(iRet == SOCKET_ERROR)
{
cprintf("Packet failed to be sent\r\n");
PrintWinsockError();
return false;
}
// Bingo
return true;
}
//////////////////////////////////////////////////////////////////////////////////////////////////////
// Application entry point
int main(int argc, char *argv[], char *envp[])
{
// Local for return value checking
int iRet;
// Used for winsock startup
WORD wVersionRequested;
WSADATA wsaData;
// Initialise winsock, latest version
wVersionRequested = MAKEWORD(2, 2);
iRet = WSAStartup(wVersionRequested, &wsaData);
if(iRet != 0)
{
WSACleanup();
cprintf("Failed to start winsock\r\n");
return false;
}
// Create a new socket
SOCKET UDP_Socket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if(UDP_Socket==INVALID_SOCKET)
{
cprintf("Failed to create socket\r\n");
PrintWinsockError();
return false;
}
// Bind socket to port
SOCKADDR_IN addrLocal;
addrLocal.sin_family = AF_INET;
addrLocal.sin_port = htons(DEFAULT_PORT);
bGetNetworkInterface(addrLocal.sin_addr); // Same as... addrLocal.sin_addr.s_addr = inet_addr("yourip");
iRet = bind(UDP_Socket, (LPSOCKADDR)&addrLocal, sizeof(struct sockaddr));
if(iRet == SOCKET_ERROR)
{
cprintf("Failed to bind socket\r\n");
PrintWinsockError();
return false;
}
cprintf("Using UDP port : %d\n", DEFAULT_PORT);
cprintf("Join multicast group : %s", MULTICAST_GROUP_IP);
// Join multicasting group
if(bJoinMulticastGroup(UDP_Socket, MULTICAST_GROUP_IP))
cprintf(" -> Done\r\n\r\n");
else
cprintf("FAILED\r\n");
while(true)
{
bReceiveMulticast(UDP_Socket, MULTICAST_GROUP_IP);
Sleep(100);
// Send a multicast packet
if(bSendMulticast(UDP_Socket, MULTICAST_GROUP_IP))
cprintf("Multicast sent to group %s\r\n", MULTICAST_GROUP_IP);
// Dont overwhelm the user
Sleep(1000);
}
// Close socket, kill winsock
closesocket(UDP_Socket);
WSACleanup();
// Quit
return iRet;
}