I want to build a chat application without server (I don't know what is called maybe it's peer-to-peer chat) using Winsock.
I just learned from this two source code :
//==================================================== file = udpServer.c =====
//= A message "server" program to demonstrate sockets programming =
//=============================================================================
//= Notes: =
//= 1) This program conditionally compiles for Winsock and BSD sockets. =
//= Set the initial #define to WIN or BSD as appropriate. =
//= 2) This program serves a message to program udpClient running on =
//= another host. =
//= 3) The steps #'s correspond to lecture topics. =
//=---------------------------------------------------------------------------=
//= Example execution: (udpServer and udpClient running on host 127.0.0.1) =
//= Waiting for recvfrom() to complete... =
//= IP address of client = 127.0.0.1 port = 55476) =
//= Received from client: Test message from CLIENT to SERVER =
//=---------------------------------------------------------------------------=
//= Build: bcc32 udpServer.c or cl udpServer.c wsock32.lib for Winsock =
//= gcc udpServer.c -lsocket -lnsl for BSD =
//=---------------------------------------------------------------------------=
//= Execute: udpServer =
//=---------------------------------------------------------------------------=
//= Author: Ken Christensen =
//= University of South Florida =
//= WWW: http://www.csee.usf.edu/~christen =
//= Email: christen@csee.usf.edu =
//=---------------------------------------------------------------------------=
//= History: KJC (08/02/08) - Genesis (from server1.c) =
//= KJC (09/07/09) - Minor clean-up =
//= KJC (09/22/13) - Minor clean-up to fix warnings =
//=============================================================================
#define WIN // WIN for Winsock and BSD for BSD sockets
//----- Include files --------------------------------------------------------
#include <stdio.h> // Needed for printf()
#include <string.h> // Needed for memcpy() and strcpy()
#include <stdlib.h> // Needed for exit()
#ifdef WIN
#include <windows.h> // Needed for all Winsock stuff
#endif
#ifdef BSD
#include <sys/types.h> // Needed for sockets stuff
#include <netinet/in.h> // Needed for sockets stuff
#include <sys/socket.h> // Needed for sockets stuff
#include <arpa/inet.h> // Needed for sockets stuff
#include <fcntl.h> // Needed for sockets stuff
#include <netdb.h> // Needed for sockets stuff
#endif
//----- Defines --------------------------------------------------------------
#define PORT_NUM 1050 // Arbitrary port number for the server
//===== Main program =========================================================
int main()
{
#ifdef WIN
WORD wVersionRequested = MAKEWORD(1,1); // Stuff for WSA functions
WSADATA wsaData; // Stuff for WSA functions
#endif
int server_s; // Server socket descriptor
struct sockaddr_in server_addr; // Server Internet address
struct sockaddr_in client_addr; // Client Internet address
struct in_addr client_ip_addr; // Client IP address
int addr_len; // Internet address length
char out_buf[4096]; // Output buffer for data
char in_buf[4096]; // Input buffer for data
int retcode; // Return code
#ifdef WIN
// This stuff initializes winsock
WSAStartup(wVersionRequested, &wsaData);
#endif
// >>> Step #1 <<<
// Create a socket
// - AF_INET is Address Family Internet and SOCK_DGRAM is datagram
server_s = socket(AF_INET, SOCK_DGRAM, 0);
if (server_s < 0)
{
printf("*** ERROR - socket() failed \n");
exit(-1);
}
// >>> Step #2 <<<
// Fill-in my socket's address information
server_addr.sin_family = AF_INET; // Address family to use
server_addr.sin_port = htons(PORT_NUM); // Port number to use
server_addr.sin_addr.s_addr = htonl(INADDR_ANY); // Listen on any IP address
retcode = bind(server_s, (struct sockaddr *)&server_addr,
sizeof(server_addr));
if (retcode < 0)
{
printf("*** ERROR - bind() failed \n");
exit(-1);
}
// >>> Step #3 <<<
// Wait to receive a message from client
printf("Waiting for recvfrom() to complete... \n");
addr_len = sizeof(client_addr);
retcode = recvfrom(server_s, in_buf, sizeof(in_buf), 0,
(struct sockaddr *)&client_addr, &addr_len);
if (retcode < 0)
{
printf("*** ERROR - recvfrom() failed \n");
exit(-1);
}
// Copy the four-byte client IP address into an IP address structure
memcpy(&client_ip_addr, &client_addr.sin_addr.s_addr, 4);
// Print an informational message of IP address and port of the client
printf("IP address of client = %s port = %d) \n", inet_ntoa(client_ip_addr),
ntohs(client_addr.sin_port));
// Output the received message
printf("Received from client: %s \n", in_buf);
// >>> Step #4 <<<
// Send to the client using the server socket
strcpy(out_buf, "This is a reply message from SERVER to CLIENT");
retcode = sendto(server_s, out_buf, (strlen(out_buf) + 1), 0,
(struct sockaddr *)&client_addr, sizeof(client_addr));
if (retcode < 0)
{
printf("*** ERROR - sendto() failed \n");
exit(-1);
}
// >>> Step #5 <<<
// Close all open sockets
#ifdef WIN
retcode = closesocket(server_s);
if (retcode < 0)
{
printf("*** ERROR - closesocket() failed \n");
exit(-1);
}
#endif
#ifdef BSD
retcode = close(server_s);
if (retcode < 0)
{
printf("*** ERROR - close() failed \n");
exit(-1);
}
#endif
#ifdef WIN
// This stuff cleans-up winsock
WSACleanup();
#endif
// Return zero and terminate
return(0);
}
and
//=========================================== file = udpClientBroadcast.c =====
//= A message "client" program to demonstrate sockets programming =
//= - This is udpClient.c modified to use broadcast =
//=============================================================================
//= Notes: =
//= 1) This program conditionally compiles for Winsock and BSD sockets. =
//= Set the initial #define to WIN or BSD as appropriate. =
//= 2) This program needs udpServer to be running on another host. =
//= Program udpServer must be started first. =
//=---------------------------------------------------------------------------=
//= Example execution: (udpServer and udpClientBroadcast on host 127.0.0.1) =
//= Received from server: This is a reply message from SERVER to CLIENT =
//=---------------------------------------------------------------------------=
//= Build: Windows: Borland: bcc32 udpClientBroadcast.c =
//= Visual C cmd line: cl udpClientBroadcast.c wsock32.lib =
//= MinGW: gcc udpClientBroadcast.c -lws2_32 =
//= Unix: gcc udpClientBroadcast.c -lnsl -o udpClientBroadcast =
//=---------------------------------------------------------------------------=
//= Execute: udpClientBroadcast =
//=---------------------------------------------------------------------------=
//= Author: Ken Christensen =
//= University of South Florida =
//= WWW: http://www.csee.usf.edu/~christen =
//= Email: christen@csee.usf.edu =
//=---------------------------------------------------------------------------=
//= History: KJC (04/10/10) - Genesis (from udpClient.c) =
//=============================================================================
#define WIN // WIN for Winsock and BSD for BSD sockets
//----- Include files ---------------------------------------------------------
#include <stdio.h> // Needed for printf()
#include <string.h> // Needed for memcpy() and strcpy()
#ifdef WIN
#include <windows.h> // Needed for all Winsock stuff
#endif
#ifdef BSD
#include <sys/types.h> // Needed for sockets stuff
#include <netinet/in.h> // Needed for sockets stuff
#include <sys/socket.h> // Needed for sockets stuff
#include <arpa/inet.h> // Needed for sockets stuff
#include <fcntl.h> // Needed for sockets stuff
#include <netdb.h> // Needed for sockets stuff
#endif
//----- Defines ---------------------------------------------------------------
#define PORT_NUM 1050 // Port number used
//===== Main program ==========================================================
void main(void)
{
#ifdef WIN
WORD wVersionRequested = MAKEWORD(1,1); // Stuff for WSA functions
WSADATA wsaData; // Stuff for WSA functions
#endif
int client_s; // Client socket descriptor
struct sockaddr_in server_addr; // Server Internet address
int addr_len; // Internet address length
char out_buf[4096]; // Output buffer for data
char in_buf[4096]; // Input buffer for data
int retcode; // Return code
int iOptVal; // Socket option value
int iOptLen; // Socket option length
#ifdef WIN
// This stuff initializes winsock
WSAStartup(wVersionRequested, &wsaData);
#endif
// Create a socket
client_s = socket(AF_INET, SOCK_DGRAM, 0);
if (client_s < 0)
{
printf("*** ERROR - socket() failed \n");
exit(-1);
}
// Fill-in server socket's address information
server_addr.sin_family = AF_INET; // Address family to use
server_addr.sin_port = htons(PORT_NUM); // Port num to use
server_addr.sin_addr.s_addr = inet_addr(INADDR_ANY); // Need this for Broadcast
// Set socket to use MAC-level broadcast
iOptVal = 1;
iOptLen = sizeof(int);
setsockopt(client_s, SOL_SOCKET, SO_BROADCAST, (char*)&iOptVal, iOptLen);
// Assign a message to buffer out_buf
strcpy(out_buf, "Test message from CLIENT to SERVER");
// Now send the message to server.
retcode = sendto(client_s, out_buf, (strlen(out_buf) + 1), 0,
(struct sockaddr *)&server_addr, sizeof(server_addr));
if (retcode < 0)
{
printf("*** ERROR - sendto() failed \n");
exit(-1);
}
// Wait to receive a message
addr_len = sizeof(server_addr);
retcode = recvfrom(client_s, in_buf, sizeof(in_buf), 0,
(struct sockaddr *)&server_addr, &addr_len);
if (retcode < 0)
{
printf("*** ERROR - recvfrom() failed \n");
exit(-1);
}
// Output the received message
printf("Received from server: %s \n", in_buf);
// Close all open sockets
#ifdef WIN
retcode = closesocket(client_s);
if (retcode < 0)
{
printf("*** ERROR - closesocket() failed \n");
exit(-1);
}
#endif
#ifdef BSD
retcode = close(client_s);
if (retcode < 0)
{
printf("*** ERROR - close() failed \n");
exit(-1);
}
#endif
#ifdef WIN
// This stuff cleans-up winsock
WSACleanup();
#endif
}
These two codes works fine for me, however these are 2 applications and I just want 1 application that can act as a server and also as a client.
So I combine these two source codes into one using a thread.
Again, the program works, but the listener socket accepts the connection from the broadcasted message.
What I want is the listener to block the incoming connection from the loopback address.
How to do that?
edit :
example I have 2 computers, one is A(192.168.1.100) and the other is B(192.168.1.101), when i run the program computer A receive the message from itself, what I want is A receive only any except A.
EDIT 27/01/2014 :
after a few days of searching i think i wasn't be able to find the solution to my problem.
however, there's an alternate way to make it possible.
first step is to get your local computer IP Address.
second step is to construct your message before it is send for example format is "ipAddress_messageToSend".
third step create function to process incoming message from recvfrom() function that will split the incoming message by "_"
so that you'll have two dimensional arrays, the first row is for IP Address where this message come from and the second is the message itself.
fourth step, you'll have to do comparation between incoming message IP Address and your computer IP Address.
you can use this code below to obtain an IP Address.
char ac[80];
gethostname(ac, sizeof(ac));
struct hostent *phe = gethostbyname(ac);
struct in_addr addr;
memcpy(&addr, phe->h_addr_list[0], sizeof(struct in_addr));
printf("IP Address is : %s\n", inet_ntoa(addr));
fifth step when the IP is compared and they're same do nothing, if not then do what you want to do.
hope this will help you all