Si ca peut aider, j'ai trouvé ces morceaux de codes ...
Voici les includes pour
linux j'ai testé sous
windows uniquement
Code:
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <stdio.h>
Voici le code qui envoie le broadcast
Code:
#include <sys/types.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#include <stdio.h>
/*
CpSc 824 -- SIMPLE datagram broadcast example...
This program broadcasts a outMessageBuf to
port 5824 (arbitrarily chosen)
and waits for replies from whatever machines receive it...
*/
#define PORTNUMBER 5824
main (argc, argv)
int argc;
char *argv[];
{
int socketDesc; /* Socket Descriptor */
int addrLength;
struct sockaddr_in destinationAddr,
myAddr,
responseAddr;
struct hostent *hostNameBufPtr;
char outMessageBuf[128];
char inMessageBuf[128];
struct timeval timeOut;
fd_set readReadySet;
int msgCount;
int trueFlag = 0x1;
int ret;
WSADATA WSAData;
ret = WSAStartup(MAKEWORD(1,1), &WSAData);
if (ret) { perror("network: FAILED ! (Winsock 2 Error: while asking for version 1.1)"); return(0); }
/* Create socket from which to send */
if ((socketDesc = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
perror("open error on socket");
exit(1);
}
/* BIND the socket on our end to any available port (i.e.
leave it up to the system to assign a port (used for
replys */
myAddr.sin_family = AF_INET;
myAddr.sin_addr.s_addr = htonl(INADDR_ANY);
myAddr.sin_port = htons(0); /* The zero says bind to any port */
if (bind(socketDesc, (struct sockaddr *) &myAddr, sizeof(myAddr))
< 0) {
perror("bind error");
exit(1);
}
/* And build BROADCAST address */
destinationAddr.sin_family = AF_INET;
destinationAddr.sin_addr.s_addr = htonl(INADDR_BROADCAST);
destinationAddr.sin_port = htons(PORTNUMBER);
/* Set the socket to permit multicasts on the local LAN */
if (setsockopt(socketDesc, SOL_SOCKET, SO_BROADCAST, &trueFlag,
sizeof(trueFlag)) != 0) {
perror("setsockopt error");
exit(1);
}
/* Broadcast message */
strcpy(outMessageBuf, "Hello world");
if (sendto(socketDesc, outMessageBuf, strlen(outMessageBuf)+1, 0,
(struct sockaddr *)&destinationAddr, sizeof(destinationAddr)) < 0) {
perror("socket send error");
exit(1);
}
/* And wait for up to 5 seconds for replys to come back */
/* Set timeOut value for receive to 5 seconds */
timeOut.tv_sec = 5L;
timeOut.tv_usec = 0L;
/* Read responses from hosts accepting the multicast until a read
finally times-out. */
FD_ZERO(&readReadySet);
FD_SET(socketDesc,&readReadySet);
msgCount = 0;
while (select(socketDesc+1,&readReadySet, NULL, NULL, &timeOut) > 0) {
addrLength= sizeof(responseAddr);
if (recvfrom(socketDesc,inMessageBuf,sizeof(inMessageBuf),0,
&responseAddr, &addrLength) < 0) {
perror("socket read error");
exit(1);
}
/* Convert the address of the responding machine to its symbolic
format */
if ((hostNameBufPtr=gethostbyaddr(&responseAddr.sin_addr.s_addr,
sizeof(responseAddr.sin_addr.s_addr), AF_INET)) == NULL) {
perror("gethostbyaddr error");
}
else {
printf("Message received from %s\n", hostNameBufPtr->h_name);
}
printf("Received Message=%s\n\n",inMessageBuf);
msgCount++;
FD_SET(socketDesc,&readReadySet);
}
printf("Received %d messages\n",msgCount);
}
La partie
WSAstartup est recupéré de raydium, a priori inutile pour
linuxLa partie reception:
Code:
#include <sys/types.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#include <stdio.h>
/*
In this example, the a "recvfrom" is used so a reply message may be
returned to the node that sent the message.
*/
#define PORTNUMBER 5824
main () {
int socketDesc;
int senderAddrLength;
struct sockaddr_in myAddr, senderAddr;
char messageBuf[1024];
struct hostent *senderNameBufPtr;
char *senderPtr;
int loopCnt;
/* For testing purposes, make sure process will terminate eventually */
//alarm(60); /* Terminate in 60 seconds */
int ret;
WSADATA WSAData;
ret = WSAStartup(MAKEWORD(1,1), &WSAData);
if (ret) { perror("network: FAILED ! (Winsock 2 Error: while asking for version 1.1)"); return(0); }
/* Create socket from which to read */
if ((socketDesc = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
perror("open error on socket");
exit(1);
}
/* Create "name" of socket */
myAddr.sin_family = AF_INET;
myAddr.sin_addr.s_addr = INADDR_ANY;
myAddr.sin_port = htons(PORTNUMBER);
if (bind(socketDesc, (struct sockaddr *) &myAddr, sizeof(myAddr)) < 0) {
perror("bind error");
exit(1);
}
/* Read from socket and then reply (note that the sender's address
is placed in "senderAddr") */
while (1) {
for (loopCnt=0;loopCnt<5;loopCnt++) {
senderAddrLength = sizeof(senderAddr);
if (recvfrom(socketDesc,messageBuf,sizeof(messageBuf),0,
&senderAddr,&senderAddrLength) < 0) {
perror("socket read error");
exit(1);
}
/* Print out the name of the machine that sent the message */
if ((senderNameBufPtr=gethostbyaddr(&senderAddr.sin_addr.s_addr,
sizeof(senderAddr.sin_addr.s_addr), AF_INET))== NULL) {
senderPtr= "(Unknown)";
}
else {
senderPtr = senderNameBufPtr->h_name;
}
printf("Received message:%s from host %s\n",messageBuf, senderPtr);
/* And return a response to the sender */
sprintf(messageBuf,"Got message %d",loopCnt);
if (sendto(socketDesc, messageBuf, strlen(messageBuf)+1, 0,
(struct sockaddr *)&senderAddr, senderAddrLength) < 0) {
perror("socket send error");
exit(1);
}
}
}
}
Les tests sous windows, j'ai un souci.
En lanceant la partie reception sur deux machines XP sur un lan.
Si l'emetteur est lancée sur une des deux machines, tout ce passe bien.
Sur l'autre l'adresse n'est pas retrouvé (unknow) donc ca ne marche pas très bien, le serveur ne recoit pas la reponse du client.
Je ne sais pas pourquoi et je n'ai pas de debugger sur la deuxième machine.
A priori le fait que l'ip ne puisse pas etre resolue en nom ne devrait pas bloquer le retour de message.
Dans l'absolue ce n'est pas génant puisque le message passe.
Enfin la meme config machine permet de faire fonctionner test6 et tests en serveur.
Je pense que des lors on peut envoyer l'ip du serveur par broadcast toutes les seconde sur le port raydium+1
Deux autres questions:
Le serveur semble gourmant en resources, la charge du processeur est assez importante, meme lorsque le serveur tourne seul.
J'ai mis le sleep(0) dans le main. Il me semble qu'un serveur n'est pas aussi gourmand ?
Le ping (delay) reporté par le serveur me semble enorme ! 1840ms pour deux machine sur un lan. Le ping entre ces machines est <1ms.
Si cela peut aider ...
Pour info le codes viennent de la:
http://www.cs.clemson.edu/~wayne/cpsc824/