我正在尝试使用UDP套接字在C中实现一个简单的倒计时应用程序。 我对应用程序的服务器部分有一个非常奇怪的问题:它应该从客户端接收一个号码,然后为倒计时发送不同的号码。因此,例如,如果用户在客户端中键入5,则服务器应该接收5并向客户端发送4,3,2,1和0。这是我的代码:
#define BUFFERSIZE 512
#define PORT 55123
void ClearWinSock()
{
#if defined WIN32
WSACleanup();
#endif
}
int main()
{
#if defined WIN32
WSADATA wsaData;
WORD wVersionRequested;
wVersionRequested = MAKEWORD(2, 2);
if(WSAStartup(wVersionRequested, &wsaData) != 0)
{
printf("Error: unable to initialize the socket!\n");
return -1;
}
#endif
int mainSocket = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
if(mainSocket < 0)
{
printf( "Error: unable to create the socket!\n");
ClearWinSock();
return -1;
}
struct sockaddr_in serverSockAddrIn;
memset(&serverSockAddrIn, 0, sizeof(serverSockAddrIn));
serverSockAddrIn.sin_family = AF_INET;
serverSockAddrIn.sin_port = htons(PORT);
serverSockAddrIn.sin_addr.s_addr = inet_addr("127.0.0.1");
if(bind(mainSocket, (struct sockaddr*) &serverSockAddrIn, sizeof(serverSockAddrIn)) < 0)
{
fprintf(stderr, "Error: unable to bind the socket!\n");
ClearWinSock();
return -1;
}
char buffer[BUFFERSIZE];
struct sockaddr_in clientAddress;
unsigned int clientAddressLength;
int recvMessageSize;
while(1)
{
clientAddressLength = sizeof(clientAddress);
recvMessageSize = recvfrom(mainSocket, buffer, BUFFERSIZE, 0, (struct sockaddr*) &clientAddress, &clientAddressLength);
int countdownValue;
sscanf(buffer, "%d", &countdownValue);
printf("\nNumber received: %d\n", countdownValue);
int index;
for(index = countdownValue - 1; index >= 0; --index)
{
itoa(index, buffer, 10);
int outputStringLength = strlen(buffer);
if(sendto(mainSocket, buffer, outputStringLength, 0, (struct sockaddr*) &clientAddress, sizeof(clientAddress)) != outputStringLength)
{
printf("Error: unable to send the message!");
}
}
}
ClearWinSock();
return 0;
}
现在的问题是,如果我,例如,从客户端发送数字5,有时服务器正常工作,有时它说“收到的数字:5”,不发送任何内容,然后它说“收到的数字:0“5次。
我认为我在使用套接字时做错了。或者它可能涉及清洁缓冲区,不知道!我无法重现错误,因为有了相同的输入,它有时会以某种方式起作用,有时也会起作用。
答案 0 :(得分:0)
您的客户端和服务器是否都在同一端口上侦听?如果是这样,您可能需要考虑让它们在不同的端口上侦听(例如,客户端发送到X并侦听端口Y;服务器发送到端口Y并侦听端口X),以便它们不会相互干扰或意外接收当客户端和服务器在同一主机上运行时,他们自己发送的数据包。
或者,您可以通过在调用bind()之前始终执行以下代码来指示客户端和服务器共享同一端口:
const int trueValue = 1;
setsockopt(mainSocket, SOL_SOCKET, SO_REUSEADDR, (const char *) &trueValue, sizeof(trueValue));