问题描述
在我们的项目中,我们必须制作一个游戏(已经完成)并允许多人游戏(使用 P2P 方法)。我已经使用 select 方法制作了“客户端”和“服务器”程序来开始(我认为将来的程序将是相同的),以便允许它们相互发送和接收消息。当我尝试从服务器向客户端发送消息(终端中写入的数字)时,没问题,但是,当我尝试从客户端向服务器执行相同操作时,什么也没发生。此外,当我开始从客户端向服务器发送消息时,它可以工作,但服务器无法发送任何内容(更准确地说,客户端没有收到任何内容)。
我不理解这种行为,所以我尝试使用线程,但我的教授说如果我使用良好的选择,我不需要它......
您会在下面找到“服务器”的代码
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/time.h>
#define FALSE 0
#define TRUE 1
typedef struct Element Element;
struct Element
{
int data_i;
Element *suivant;
};
typedef struct
{
Element *premier;
} File;
void initialise(File *file)
{
file->premier = NULL;
}
int enfiler(File *file,long long nbre)
{
if (file == NULL)
{
printf("Il faut initialiser la file");
return EXIT_FAILURE;
}
Element *new_el = malloc(sizeof(Element));
new_el->suivant = NULL;
new_el->data_i = nbre;
if (file->premier != NULL)
{
Element *elementActuel = file->premier;
while (elementActuel->suivant != NULL)
{
elementActuel = elementActuel->suivant;
}
elementActuel->suivant = new_el;
printf("j'ai bien enfilé le message\n");
return EXIT_SUCCESS;
}
else
{
file->premier = new_el;
printf("j'ai bien enfilé le message\n");
return EXIT_SUCCESS;
}
return EXIT_FAILURE;
}
Element defiler(File *file)
{
if (file != NULL && file->premier != NULL)
{
Element *el = malloc(sizeof(Element));
el = file->premier;
file->premier = file->premier->suivant;
free (el);
return *el;
}
//voir quoi retourner lors d'erreurs
}
void stop(char * msg){
perror(msg);
exit(EXIT_FAILURE);
}
typedef struct {
int fd;
}client_info;
int main(int argc,char *argv[]){
//Variables
int opt = TRUE;
int master_socket=0,new_socket=0,max_client = 30,activity=0,i=0;
int max_sd = 0;
client_info client_tab[max_client];
struct sockaddr_in address;
int addr_len=0;
fd_set readfds;
long long message=0;
int64_t buffer=0;
int smess = 0;
int sd =0;
write(0,"initialisation\n",15);
//initializing the "file"
File file_mess,file_recus;
initialise(&file_mess);
initialise(&file_recus);
//Initializing files descriptors
for (i = 0; i < max_client; i++)
{
client_tab[i].fd = -1;
}
//create a master socket
if( (master_socket = socket(AF_INET,SOCK_STREAM,0)) == 0)
{
perror("socket Failed");
exit(EXIT_FAILURE);
}
if( setsockopt(master_socket,SOL_SOCKET,SO_REUSEADDR,(char *)&opt,sizeof(opt)) < 0 )
{
perror("setsockopt");
exit(EXIT_FAILURE);
}
//Initializing address
address.sin_family = AF_INET;
inet_aton("127.0.0.1",&address.sin_addr);
address.sin_port = htons( 1234 );
addr_len = sizeof(address);
//Configurating master_socket to listen to new connections .
if(bind(master_socket,(const struct sockaddr *)&address,addr_len)<0) stop("binding error");
if(listen(master_socket,3)<0) stop("Problem initializing master_socket");
printf("Enterring while\n");
while(TRUE){
//clear the socket set
FD_ZERO(&readfds);
//add master socket to set
FD_SET(master_socket,&readfds);
FD_SET(STDIN_FILENO,&readfds);
max_sd = master_socket;
//add child sockets to set
for ( i = 0 ; i < max_client ; i++)
{
//socket descriptor
sd = client_tab[i].fd;
//if valid socket descriptor then add to read list
if(sd > 0)
FD_SET( sd,&readfds);
//highest file descriptor number,need it for the select function
if(sd > max_sd)
max_sd = sd;
}
activity = select( max_sd + 1,&readfds,NULL,NULL);
if ((activity < 0) && (errno!=EINTR)) stop("select error");
if (FD_ISSET(master_socket,&readfds))
{
if ((new_socket = accept(master_socket,(struct sockaddr *)&address,(socklen_t*)&addr_len))<0) stop("accepting problem");
for (i = 0; i < max_client; i++)
{
//if position is empty
if( client_tab[i].fd == -1 )
{
client_tab[i].fd = new_socket;
printf("Adding to list of sockets as %d\n\n",i);
// Après avoir ajouté le client dans le tableau,le serveur lui renvoie un id (valeur de i)
if(send(client_tab[i].fd,&i,sizeof(int),0) == -1) stop("recv() : envoi de l'id");
break;
}
}
}
//else its some IO operation on some other socket :)
for (i = 0; i < max_client; i++)
{
sd = client_tab[i].fd;
if (FD_ISSET( sd,&readfds) && sd!=-1)
{
//Check if it was for closing,and also read the incoming message
if ((smess = recv( sd,(char *)&buffer,__SIZEOF_LONG_LONG__,0)) == 0)
{
//Somebody disconnected,get his details and print
getpeername(sd,(struct sockaddr*)&address,(socklen_t*)&addr_len);
printf("%i disconnected.\n",i);
//Close the socket and mark as 0 in list for reuse
close( sd );
client_tab[i].fd = -1;
}
else{
message = ntohl(buffer);
buffer=0;
printf("Message reçu de %i : %lli\n",i,message);
enfiler (&file_recus,message);
message = 0;
}
}
}
if(FD_ISSET(STDIN_FILENO,&readfds)){
scanf("%lli",&message);
enfiler(&file_mess,message);
buffer = htonl(file_mess.premier->data_i);
for (i = 0; i < max_client; i++)
{
if(client_tab[i].fd != -1) send(client_tab[i].fd,&buffer,sizeof(buffer),0);
}
printf("J'ai bien envoyé : %lli\n",message);
defiler(&file_mess);
buffer = 0;
message=0;
}
if (file_mess.premier != NULL)
{
printf("regarde si des trucs à envoyer\n");
buffer = htonl(file_mess.premier->data_i);
//envoie à tout le monde
for (i = 0; i < max_client; i++)
{
if (client_tab[i].fd != -1)
{
send(client_tab[i].fd,0);
}
}
printf("envoyé\n");
defiler(&file_mess);
buffer=0;
}
}
}
这里是“客户”:
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <netinet/in.h>
#include <netdb.h>
#include <arpa/inet.h>
#define BUFSIZE 100
#define TRUE 1
#define FALSE 0
typedef struct Element Element;
struct Element
{
int data_i;
Element *suivant;
};
typedef struct
{
Element *premier;
} File;
void initialise(File *file)
{
file->premier = NULL;
}
int enfiler(File *file,long long nbre)
{
if (file == NULL)
{
printf("Il faut initialiser la file");
return EXIT_FAILURE;
}
Element *new_el = malloc(sizeof(Element));
new_el->suivant = NULL;
new_el->data_i = nbre;
if (file->premier != NULL)
{
Element *elementActuel = file->premier;
while (elementActuel->suivant != NULL)
{
elementActuel = elementActuel->suivant;
}
elementActuel->suivant = new_el;
printf("j'ai bien enfilé le message\n");
return EXIT_SUCCESS;
}
else
{
file->premier = new_el;
printf("j'ai bien enfilé le message\n");
return EXIT_SUCCESS;
}
return EXIT_FAILURE;
}
Element defiler(File *file)
{
if (file != NULL && file->premier != NULL)
{
Element *el = malloc(sizeof(Element));
el = file->premier;
file->premier = file->premier->suivant;
free(el);
return *el;
}
}
void stop(char *msg)
{
perror(msg);
exit(EXIT_FAILURE);
}
int main(int argc,char *argv[])
{
//Creating a TCP|IPV4 socket
int sockfd = socket(AF_INET,0);
if (sockfd == -1)
stop("Probleme de socket");
//Creating the socket
struct sockaddr_in serv_addr;
bzero(&serv_addr,sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(1234);
inet_aton("127.0.0.1",&serv_addr.sin_addr);
//initializing the "file"
File file_mess,file_recus;
initialise(&file_mess);
initialise(&file_recus);
//initiliazing the file descriptor set
fd_set readfds;
FD_ZERO(&readfds);
if (connect(sockfd,(struct sockaddr *)&serv_addr,sizeof(serv_addr)) < 0)
stop("Connection error");
int id = 0;
if(recv(sockfd,&id,0) == -1) stop ("recv() : reception de l'id"); // Le client récupère son id
printf("Mon id : %i\n",id);
FD_SET(sockfd,&readfds);
FD_SET(STDIN_FILENO,&readfds);
//Variables
int nSelect = 0;
int n;
long long mess = 0;
int64_t fmess = 0;
while (TRUE)
{
nSelect = select(sockfd + 1,NULL);
if (nSelect < 0)
stop("Select error");
if (FD_ISSET(STDIN_FILENO,&readfds))
{
scanf("%lli",&mess);
fmess = htonl(mess);
send(sockfd,&fmess,sizeof(fmess),0);
printf("J'ai bien envoyé : %lli\n",mess);
mess = 0;
}
if (file_mess.premier != NULL)
{
send(sockfd,&file_mess.premier->data_i,sizeof(file_mess.premier->data_i),0);
defiler(&file_mess);
}
if (FD_ISSET(sockfd,&readfds))
{
printf("reçu\n");
if ((n=recv(sockfd,&mess,sizeof(long long),0)) < 0)
stop("recv(");
else if (n==0)
{
printf("déconnexion...\n");
close(sockfd);
return EXIT_SUCCESS;
}
else
{
printf("cc\n");
mess = ntohl(fmess);
fmess = 0;
printf("Message reçu: %lli\n",mess);
enfiler(&file_recus,mess);
mess = 0;
}
}
}
exit(0);
}
在这里,您会找到我的测试:
1-客户端通过发送 13 开始对话,但没有收到服务器尝试发送的内容
2-然后,服务器开始会话发送 15,客户端没有收到它,他什么也不发送
PS:文件的使用是为了对数据进行良好的处理(我会制定一个协议[使用长长的数字],所以我必须在发送前和接收后处理数据)。最后,这段代码还允许给出一个数字来识别玩家(并知道接收到的数据是给谁的)。
解决方法
暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!
如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。
小编邮箱:dio#foxmail.com (将#修改为@)