UDPを使ってネットワークシステムを作ろうとしています。なんとか動作させることができましたが、メッセージを待たずにプログラムを続行できるように、リッスン部分を別のスレッドに入れたいと思います (ゲームに使用されます)。
問題は、ソケットを新しいスレッドに渡してリッスンに使用すると、それが機能せず、常にランダムな入力を受け取ることです。ソケットを初期化するメソッドでまったく同じコードを使用すると、すべて正常に動作します。
これは機能します:
bool serverUDP() {
WSADATA w;
SOCKET sd;
struct sockaddr_in server, client;
char buffer[DEFAULT_BUFLEN];
int bytes_received;
int client_length;
/* Open windows connection */
if (WSAStartup(MAKEWORD(2,2)/*0x0101*/, &w) != 0) {
fprintf(stderr, "Could not open Windows connection.\n");
return false;
}
/* Open a datagram socket */
sd = socket(AF_INET, SOCK_DGRAM, 0);
if (sd == INVALID_SOCKET) {
fprintf(stderr, "Could not create socket.\n");
WSACleanup();
return false;
}
/* Clear out server struct */
memset((void *)&server, '\0', sizeof(struct sockaddr_in));
/* Set family and port */
server.sin_family = AF_INET;
server.sin_port = htons(atoi(DEFAULT_PORT));
server.sin_addr.S_un.S_un_b.s_b1 = 127;
server.sin_addr.S_un.S_un_b.s_b2 = 0;
server.sin_addr.S_un.S_un_b.s_b3 = 0;
server.sin_addr.S_un.S_un_b.s_b4 = 1;
/* Bind address to socket */
if (bind(sd, (struct sockaddr *)&server, sizeof(struct sockaddr_in)) == -1) {
fprintf(stderr, "Could not bind name to socket.\n");
closesocket(sd);
WSACleanup();
return false;
}
client_length = (int)sizeof(struct sockaddr_in);
/* Receive bytes from client */
while (true) {
bytes_received = recvfrom(sd, buffer, DEFAULT_BUFLEN, 0, (struct sockaddr *)&client, &client_length);
fprintf(stderr,"received: %s\n", buffer);
}
closesocket(sd);
WSACleanup();
return true;
}
これはしません:
bool serverUDP() {
WSADATA w;
SOCKET sd;
struct sockaddr_in server, client;
char buffer[DEFAULT_BUFLEN];
int bytes_received;
int client_length;
/* Open windows connection */
if (WSAStartup(MAKEWORD(2,2)/*0x0101*/, &w) != 0) {
fprintf(stderr, "Could not open Windows connection.\n");
return false;
}
/* Open a datagram socket */
sd = socket(AF_INET, SOCK_DGRAM, 0);
if (sd == INVALID_SOCKET) {
fprintf(stderr, "Could not create socket.\n");
WSACleanup();
return false;
}
/* Clear out server struct */
memset((void *)&server, '\0', sizeof(struct sockaddr_in));
/* Set family and port */
server.sin_family = AF_INET;
server.sin_port = htons(atoi(DEFAULT_PORT));
server.sin_addr.S_un.S_un_b.s_b1 = 127;
server.sin_addr.S_un.S_un_b.s_b2 = 0;
server.sin_addr.S_un.S_un_b.s_b3 = 0;
server.sin_addr.S_un.S_un_b.s_b4 = 1;
/* Bind address to socket */
if (bind(sd, (struct sockaddr *)&server, sizeof(struct sockaddr_in)) == -1) {
fprintf(stderr, "Could not bind name to socket.\n");
closesocket(sd);
WSACleanup();
return false;
}
_beginthread((void(*)(void*))receiveThread,0,(void *)sd);
closesocket(sd);
WSACleanup();
return true;
}
void receiveThread(SOCKET sd)
{
struct sockaddr_in client, server;
char buffer[DEFAULT_BUFLEN];
int bytes_received;
int client_length;
client_length = (int)sizeof(struct sockaddr_in);
while (true) {
bytes_received = recvfrom(sd, buffer, DEFAULT_BUFLEN, 0, (struct sockaddr *)&client, &client_length);
fprintf(stderr,"received: %s\n", buffer);
}
}
コードの 2 番目の部分は、あたかも何らかの奇妙なメッセージを常に受け取っているかのように、ランダムな入力をスパムするだけです。コードの最初の部分は、メッセージを待機し、メッセージを取得すると続行します (クライアント部分もあります)。
ご協力いただきありがとうございます!
乾杯、
マキシム・シューメーカー