2013-03-12 3 views
0

Я создал одно эхо-приложение для сервера и единого клиента. Он отлично работает для одного сервера и одного клиента. Но теперь я хочу сделать его более практичным, обрабатывая несколько клиентов для одного сервера. Я столкнулся с идеей использования функции listen() на стороне сервера для обработки нескольких клиентских подключений, но затем я узнал, что прослушивание используется только для TCP. Пожалуйста, помогите мне с этим. ниже - мой функциональный код для одного сервера и единого клиента. Помогите мне в том, как я могу изменить его, чтобы сделать односерверное приложение с несколькими серверами.Один сервер, несколько клиентов UDP-приложение в C (Winsock)

SERVER:

#define PORT 8888 //The port on which to listen for incoming data 

int main() 
{ 

SOCKET s; 
struct sockaddr_in serverSocket, clientSocket; 

char receiveBuffer[1000]; 
//int receiveBufferLength=1000; 
int clientSocketLength; 
int recv_len; 

clientSocketLength = sizeof(clientSocket) ; 

WSADATA wsa; 
//Initialise winsock 
printf("\nInitialising Winsock..."); 
if (WSAStartup(MAKEWORD(2,2),&wsa) != 0) 
{ 
    printf("Failed. Error Code : %d",WSAGetLastError()); 
    exit(EXIT_FAILURE); 
} 
printf("Socket Initialised.\n"); 

//Create a socket 
if((s = socket(AF_INET , SOCK_DGRAM , 0)) == INVALID_SOCKET) 
{ 
    printf("Could not create socket : %d" , WSAGetLastError()); 
} 
printf("Socket created.\n"); 

//Prepare the sockaddr_in structure 
serverSocket.sin_family = AF_INET; 
serverSocket.sin_addr.s_addr = INADDR_ANY; 
serverSocket.sin_port = htons(PORT); 

//Bind 
if(bind(s ,(struct sockaddr *)&serverSocket , sizeof(serverSocket)) == SOCKET_ERROR) 
{ 
    printf("\nBind failed with error code : %d" , WSAGetLastError()); 
    exit(EXIT_FAILURE); 
} 
printf("Bind done\n\n"); 

//keep listening for data 

while(1) 
{ 
    printf("\n\t\t\tWaiting for data...\n"); 
    fflush(stdout); 
    //receiveBuffer[2000]=NULL; 

    if((recv_len = recvfrom(s, receiveBuffer, 1000, 0, (struct sockaddr *) &clientSocket, &clientSocketLength)) == SOCKET_ERROR) 
    { 
     printf("\n\nrecvfrom() failed with error code : %d" , WSAGetLastError()); 
     //exit(EXIT_FAILURE); 
     while(1); 
    } 

    //print details of the client/peer and the data received 
    printf("\n\nReceived packet from %s:%d\n", inet_ntoa(clientSocket.sin_addr), ntohs(clientSocket.sin_port)); 
    printf("\nClient Says: "); 
     printf(receiveBuffer,recv_len); 



    //now reply the client with the same data 
    if (sendto(s, receiveBuffer, recv_len, 0, (struct sockaddr*) &clientSocket, clientSocketLength) == SOCKET_ERROR) 
    { 
     printf("\nsendto() failed with error code : %d" , WSAGetLastError()); 
     // exit(EXIT_FAILURE); 
     while(1); 
    } 
    else 
     printf("\nMessage Sent Back to Client"); 

} 

closesocket(s); 
WSACleanup(); 
return 0; 

} 

КЛИЕНТ:

#define PORT 8888 //The port on which to listen for incoming data 
#define SERVER "10.0.1.25" //ip address of udp server 
//#define PORT 8888 //The port on which to listen for incoming data 

int main(void) 
{ 
struct sockaddr_in connectedSocket; 

int s; 
int length=sizeof(connectedSocket); 

char receiveBuffer[1000]; 
char message[1000]; 

//clear the buffer by filling null, it might have previously received data 
memset(receiveBuffer,'\0', 1000); 

WSADATA wsa; 
//Initialise winsock 
printf("\nInitialising Winsock...\n"); 
if (WSAStartup(MAKEWORD(2,2),&wsa) != 0) 
{ 
    printf("\nFailed. Error Code : %d",WSAGetLastError()); 
    exit(EXIT_FAILURE); 
} 
printf("\n.........Initialised.\n"); 


//create socket 
if ((s=socket(AF_INET, SOCK_DGRAM, 0)) == SOCKET_ERROR) 
{ 
    printf("\n\nsocket() failed with error code : %d" , WSAGetLastError()); 
    exit(EXIT_FAILURE); 
} 


//setup address structure 
memset((char *) &connectedSocket, 0, sizeof(connectedSocket)); 
connectedSocket.sin_family = AF_INET; 
connectedSocket.sin_port = htons(PORT); 
//connectedSocket.sin_port = INADDR_BROADCAST; 
connectedSocket.sin_addr.S_un.S_addr = inet_addr(SERVER); 

while(1) 
{ 
    printf("\n\n\nEnter message : "); 
    gets(message); 

    //send the message 
    if (sendto(s, message,sizeof(message) , 0 , (struct sockaddr *) &connectedSocket, sizeof(connectedSocket)) == SOCKET_ERROR) 
    { 
     printf("\nsendto() failed with error code : %d" , WSAGetLastError()); 
     exit(EXIT_FAILURE); 
    } 

     printf("\nMessage Successfully sent to Server"); 
     // fflush(stdout); 

    if (recvfrom(s, receiveBuffer, 1000, 0, (struct sockaddr *) &connectedSocket,&length) == SOCKET_ERROR) 
    { 
     printf("\nrecvfrom() failed with error code : %d" , WSAGetLastError()); 
     exit(EXIT_FAILURE); 
    } 

    printf("\nServer Says : "); 
    printf(receiveBuffer,sizeof(receiveBuffer)); 

} 

closesocket(s); 
WSACleanup(); 

return 0; 

} 
+0

Кто-нибудь, кто может мне помочь? – Ayse

ответ

2

Позвольте мне объяснить кое-что для вас, что может привести к путанице.

Во-первых, на вашем сервере вам необходимо установить serverSocket.sin_addr.s_addr в INADDR_ANY, даже если вы хотите транслировать. Вы не хотите делать это INADDR_BROADCAST. Это просто говорит серверу связывать на любом IP-адрес вашего компьютера, потому что на одном компьютере может быть более 1 IP. Что вы делаете правильно.

Но как вы можете транслировать с сервера? Вы должны использовать setsockopt с SO_BROADCAST параметром, как это ...

int options = 1; 
if ((setsockopt(s, SOL_SOCKET, SO_BROADCAST,(char *)&options,sizeof(options))) < 0){ 
    printf("%d",WSAGetLastError()); 
} 

Это сделает ваш сервер слушает для передач, но как вы можете отправить трансляции? Вам необходимо установить INADDR_BROADCAST в поле s_addr в sockaddr структура перед вызовом sendto функция.

clientSocket.sin_addr.s_addr = INADDR_BROADCAST; 

Затем используйте sendto с clientSocket чтобы boardcast ваш messsage назад.

Во-вторых, в вашем клиентском коде у вас есть два варианта в зависимости от вашего приложения.

  1. Если вы хотите, чтобы ваши клиенты, чтобы отправить сообщение первым на сервер (прямой без трансляции), то вы делаете это правильно, установив inet_addr(SERVER) таким образом, клиент отправить сообщение только на сервере.

  2. Но, если вы хотите, чтобы клиент, чтобы передать сообщение, то вам необходимо использовать setsockopt снова в вашем клиенте, так же, как на сервере, и установить адрес в connectSocket структуре INADDR_BROADCAST.

И, наконец, было бы лучше, если бы вы сказали нам, что вы пытаетесь выполнить здесь. Если вы хотите, чтобы клиенты сначала подключились к серверу, тогда сервер объявит клиенту другим клиентам, тогда вместо TCP можно использовать TCP вместо UDP.

+0

: Это было действительно полезно – Ayse

+0

Done Broadcasting, следуя инструкциям, но мне пришлось использовать bind() на стороне клина: | – Ayse

+0

: Это было действительно полезно – Ayse

Смежные вопросы