我有一个用C编写的服务器-客户端程序。我的问题是我有一个while循环,可以在其中接收和发送数据。当我需要服务器做其他事情时,它会发生很多,但是它只是停在recv()函数上,并等待来自客户端的数据。我该如何克服?我已经尝试过:
int waitForAnswer =1;
if((childpid = fork()) == 0){
close(socketfd);
close(fd[0]);
while(1){
if(waitForAnswer) {
receive(newSocket, buff) == 0;
parseRecvMess(buff);
}
waitForAnswer =0;
但是它不起作用。由于某种原因,程序在接受带有“无套接字”错误的套接字时以退出代码1结尾。 这是我的程序;
nt main(){
int size = 256;
char buff[size];
char sbuff[size];
int n;
int reader;
int socketfd, ret;
struct sockaddr_in serverAddr;
int newSocket = -2;
struct sockaddr_in newAddr;
socklen_t addr_size;
pid_t childpid;
pocet_hracu = 0;
srand(time(NULL));
initializeLobby();
memset(buff, 0, size);
memset(sbuff, 0, size);
socketfd = socket(AF_INET,SOCK_STREAM,0);
if(socketfd < 0){
printf("\n error in socket creation");
return -1;
}
printf("\n Server socket is created\n");
memset(&serverAddr, '\0', sizeof(serverAddr));
serverAddr.sin_family = AF_INET;
serverAddr.sin_port = htons(PORT);
serverAddr.sin_addr.s_addr = inet_addr("127.0.0.1");
ret = bind(socketfd, (struct sockaddr*)&serverAddr, sizeof(serverAddr));
if(ret < 0){
printf("Error in binding\n");
return -1;
}
printf("[*]Bind to port %d\n", PORT);
if(listen(socketfd, 10) == 0){
printf("Listening...\n");
}else{
printf("Error in binding\n");
}
// pipe pro komunikaci
int readpipe;
int writepipe;
int fd[2];
pipe(fd);
for (;;) {
newSocket = accept(socketfd, (struct sockaddr *) &newAddr, &addr_size);
if (newSocket < 0) {
printf("No socket\n");
exit(1);
}
// struct timeval tv;
// tv.tv_sec = 1;
// tv.tv_usec = 0;
// setsockopt(socketfd, SOL_SOCKET, SO_RCVTIMEO, (const char*)&tv, sizeof(tv));
// read the message from client and copy it in buffer
receive(newSocket, buff);
parseRecvMess(buff);
printf("\n%s sent: %s", user, command);
if (strncmp(" new", command, 4) == 0) {
player newPlayer;
newPlayer.name = (char *) malloc(sizeof(char) * 10); // *login must contain up to 10 characters
strcpy(newPlayer.name, user);
newPlayer.gameScore = 0;
newPlayer.roundScore = 0;
newPlayer.socket = newSocket;
// TODO vztvorit pipe pro kounikaci
// newPlayer.readpipe
// newPlayer.writepipe
addToPlayersArray(&newPlayer); //TODO player index is not increasing
addToLobby(&newPlayer);
printf("Server : %s uspesne prihlasen.\n", newPlayer.name);
}
bzero(buff, size);
printf("To client : OK\n");
strcpy(sbuff, "OK\n" );
sendMess(newSocket, sbuff, sizeof(sbuff));
int waitForAnswer =1;
if((childpid = fork()) == 0){
close(socketfd);
close(fd[0]);
while(1){
printf("MAIN->while(1)\n");
// poslouchame zpravy
//if(waitForAnswer) {
receive(newSocket, buff) == 0;
parseRecvMess(buff);
//}
waitForAnswer =0;
if(strcmp(buff,":exit") == 0){
printf("Disconnected from %s:%d\n", inet_ntoa(newAddr.sin_addr), ntohs(newAddr.sin_port));
break;
} else{
// send buff to parent
int i = findPlayerIndex();
memset(sbuff, '\0', size) ;
str str;
strcat(sbuff, "//:");
sprintf(str, "%d", i);
strcat(sbuff, str);
strcat(sbuff, ":");
strcat(sbuff, command);
strcat(sbuff, "\n");
write(fd[1], sbuff , strlen(sbuff)+1);
bzero(buff, sizeof(buff));
if (strncmp("roll", command, 4) == 0) {
//TODO
hod();
}
if (strncmp("none", command, 4) == 0) {
//TODO
}
strcpy(sbuff, "OK\n" );
write(newSocket, sbuff, strlen(sbuff));
bzero(buff, sizeof(buff));
bzero(sbuff, sizeof(sbuff));
}
}
}
close(fd[1]);
int nbytes = read(fd[0], buff, sizeof(buff));
printf("PARENT: buffer : %s\n",buff);
parseRecvMess(buff);
char *index1= (char *)malloc(sizeof(char)*10);
strcpy(index1, user);
int index = atoi(index1);
char *command1= (char *)malloc(sizeof(char)*10);
strcpy(command1, command);
//printf("PARENT - index:%d, command:%s\n", index, command );
printf("PARENT - index:%d, jmeno:%s, command:%s\n", index, players_array[index].name, command1 );
bzero(buff, sizeof(buff));
if (strncmp("room", command1, 4) == 0) {
// vlozit do mistnosti
printf("command = room\n");
command = strtok(command1," ");
command = strtok(NULL," "); // volba
printf("command(volba): + %s \n", command);
//int i = findPlayerIndex(); // find player in array based on user name
printf("player index: = %d \n", index);
//printPlayer(&players_array[i]);
volbaHry(&players_array[index], command, lobby);
//players_array[i].mist->pocet_hracu++;
printf("PARENT: array pocet hracu %d\n",players_array[index].mist->pocet_hracu);
printf("PARENT: lobby pocet hracu %d\n",lobby[0].pocet_hracu);
str str;
memset(sbuff, '\0', size);
//pokud v mistnosti jsou 2 hraci => zacina hra
if( players_array[index].mist->pocet_hracu == 2){
printf("Hra zacina ...\n");
hra(players_array[index].mist);
}
printMistnost(players_array[index].mist);
}
//players_array[index].mist = lobby[volba - 1];
// }
}
close(newSocket);
return 0;
}
这是我的receive()函数:
int receive(int socket, char *buff){
int size = 256;
int reader = recv(socket, buff, size * sizeof(char), 0);
if (reader == -1) {
printf("BREAK reader == -1\n");
perror("recv()");
return(-1);
} else if (reader == 0) {
printf("BREAK reader == 0\n");
return(-2);
} else if(checkMessage(buff) == 0){
printf("ERROR: recieved message is not valid\n");
return(-3);
}
return 0;
}
如果我不使用waitForAnswer变量,则程序将与客户端连接而没有任何错误,但有时在等待另一条消息时会在开始时停止。
答案 0 :(得分:1)
使用无阻塞标志调用recv:
recv(socket, buff, size, MSG_DONTWAIT);
如果没有要读取的数据,该函数将立即返回。
答案 1 :(得分:1)
如果套接字设置为非阻塞,您还可以使用ioctl()检查数据
#include <sys/ioctl.h>
int status;
do{
ioctl(socketfd, FIONREAD, &status);
if( status > 0 ){
//packet waiting to be read
recv(socketfd, buff, size * sizeof(char), 0);
}
else{
// no data .. so do something else
}
} while (!must_stop);