Я новичок в программировании сокетов и многопоточности, я все еще учусь этому, но у меня есть проблема, которую я не могу решить, по некоторым другим темам я нашел некоторые ответы, но они, кажется, не имеютта же проблема, что и у меня.
Я хотел бы создать UDP-клиент.Этот клиент должен иметь возможность отправлять (sendto()
) и получать (recvfrom()
).
Я использую многопоточность функции отправки и получения, но recvfrom()
возвращает ошибку 10022 при вызовеWSAGetLastError()
.
Я использую библиотеку pthread.h
для многопоточности и winsock2.h
для сокета.
Когда я не многопоточен, проблем нет.
Мой код:
#include <sys/types.h>
#include <winsock2.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#pragma comment(lib,"ws2_32.lib")
#define SERVER "127.0.0.1"
#define PORT 8888
#define MAXBUFFER 1024
void Sending(void *VarThread);
void Receiving(void *VarThread);
int main(int argc, char **argv)
{
int sock;
pthread_t Thread_ID_1;
pthread_t Thread_ID_2;
WSADATA WSAData;
WSAStartup(MAKEWORD(2, 0), &WSAData);
sock = socket(AF_INET, SOCK_DGRAM, 0);
if (sock == -1)
{
perror("\nsocket()");
printf("%d", WSAGetLastError());
exit(0);
}
pthread_create(&Thread_ID_1, NULL, Sending, (void *)&sock);
pthread_create(&Thread_ID_2, NULL, Receiving, (void *)&sock);
pthread_join(Thread_ID_1, NULL);
pthread_join(Thread_ID_2, NULL);
close(sock);
WSACleanup();
return 0;
}
void Sending(void *VarThread)
{
int sock = *(int *)VarThread;
int i;
struct sockaddr_in si;
si.sin_family = AF_INET;
si.sin_addr.s_addr = inet_addr(SERVER);
si.sin_port = htons(PORT);
char buff[MAXBUFFER];
ssize_t message;
while(1)
{
fgets(buff, MAXBUFFER, stdin);
for(i = 1; i < MAXBUFFER; i++) // delete the last '\n'
{
if(buff[i] == '\0')
{
buff[i - 1] = '\0';
i = MAXBUFFER;
}
}
message = sendto(sock, buff, MAXBUFFER, 0, (struct sockaddr *)&si, sizeof(si));
if (message == -1)
{
perror("\nsendto()");
printf("%d", WSAGetLastError());
}
}
}
void Receiving(void *VarThread)
{
int sock = *(int *)VarThread;
char buff[MAXBUFFER];
ssize_t recu;
while(1)
{
recu = recvfrom(sock, buff, MAXBUFFER, 0, NULL, 0);
if(recu == -1)
{
perror("\n\nError recvfrom ");
printf("Error Code : %d", WSAGetLastError());
}
else
{
printf("message = %s\n", buff);
}
}
}
(на моей машине также запущен сервер пинг-понга для проверки кода)
Когда я запускаю это приложение, recvfrom()
isn '• блокировать и возвращать ошибку 10022
, пока я не использую функцию Sending()
.Именно тогда, когда я использую fgets()
, recvfrom()
перестает возвращать ошибку.
Как я могу предотвратить возникновение этой ошибки?
PS: моя машина работает под Windows 10.
РЕДАКТИРОВАТЬ:
Я пробовал что-то еще, я использую bind()
в функции Receiving()
, но это не работает, вот мой код:
void *Receiving(void *VarThread)
{
int sock = *(int *)VarThread;
struct sockaddr_in SockRecv;
int slen = sizeof(SockRecv);
char buff[MAXBUFFER];
ssize_t recu;
memset((char *)&SockRecv, 0, sizeof(SockRecv));
SockRecv.sin_family = AF_INET;
SockRecv.sin_addr.s_addr = htonl(SERVER);
SockRecv.sin_port = htons(PORT);
if(bind(sock, (struct sockaddr *)&SockRecv, sizeof(SockRecv)) == -1)
{
perror("\n\nbind()");
printf("Error Code : %d", WSAGetLastError());
exit(0);
}
while(1)
{
recu = recvfrom(sock, buff, MAXBUFFER, 0, (struct sockaddr *)&SockRecv, &slen);
if(recu == -1)
{
perror("\n\nError recvfrom()");
printf("Error Code : %d", WSAGetLastError());
}
else
{
printf("Message = %s\n", buff);
}
}
}