我创建了单个服务器和单个客户端回显应用程序。它适用于单个服务器和单个客户端。但是现在我想通过为单个服务器处理多个客户端来使其更加实用。我遇到了在服务器端使用listen()函数来处理多个客户端连接的想法,但后来我才知道listen只用于TCP。请帮助我。下面是我的单个服务器和单个客户端的功能代码。帮助我如何修改它以生成单服务器多客户端应用程序。
服务器:
#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 :(得分: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
函数之前,您需要在 sockaddr 结构的s_addr
字段中设置sendto
。
clientSocket.sin_addr.s_addr = INADDR_BROADCAST;
然后使用sendto
与clientSocket
一起制作麻烦。
其次,在您的客户端代码中,根据您的应用程序,您有两个选项。
如果您希望您的客户端首先向服务器发送消息(直接无需广播),那么您通过设置inet_addr(SERVER)
正确地执行此操作,以便客户端仅将消息发送到您的服务器。 p>
但是,如果您希望客户端广播该消息,则需要在客户端中再次使用setsockopt
,与服务器中相同,并在connectSocket
结构中设置地址到INADDR_BROADCAST
。
最后,如果你告诉我们你想在这里完成什么会更好。如果您希望客户端首先连接到服务器,那么服务器将客户端告知其他客户端,那么您可能需要使用TCP而不是UDP。