panthip
29-09-2005, 05:47
Ich bin dabei ein rudimentaeres Chatprogramm zu schreiben.
Momentan bin ich noch dabei den Server aufzusetzen. Die Kommunikation laeuft ueber Sockets. Der Server hat dabei ein Parentprozess der auf der socket auf Verbindungen wartet.
Meldet sich ein Client, wird ein Childprozess aufgerufen (fork()), der dann die Verbindung abhoert und auf eine receive wartet.
Das ganze soll nur fuer zwei clients funktionieren. Zunaechst blocked der parents also bis zwei clients sich verbunden haben.
Dann wartet der Parentprozess bis die Childprozesse fertig sind.
Die Childprozesse warten jeweils auf ein receive von ihren Verbindungen und senden jenes dann an die jeweilig andere Verbindung.
Jetzt hab ich das verrueckte Problem, dass der erste verbunde Client nachrichten zwar empfangen kann, allerdings keine senden. Der send Befehl meldet jeweils "bad file descriptor". Der spaeter verbundene Client kann aber beides.
Ich post hier mal den code von dem ich denke, dass er die relevanten Stellen zeigt, falls mehr Infos benoetigt werden lasst es mich wissen. Ich waere ueber jede Hilfe dankbar.
// Parentprozess:
while(1) {
sin_size = sizeof(struct sockaddr_in);
// Client1 verbindet
if ((newClientConnection[0] = accept(sockfd,
(struct sockaddr *)&their_addr, &sin_size)) == -1) {
perror("accept");
}
clientPid[0] = fork();
// wirf ersten child aus der schleife
if (getpid() != parentPid) {
break;
}
// uebergib die Verbindungskennung der 1. Verbindung an den 1.Childprozess (1a)
sprintf(pipeMessage, "%i", newClientConnection[0]);
write(pfds[1], pipeMessage,strlen(pipeMessage));
sleep(1);
// Client2 verbindet
if ((newClientConnection[1] = accept(sockfd,
(struct sockaddr *)&their_addr, &sin_size)) == -1) {
perror("accept");
}
// uebergib die Verbindungskennung der 2. Verbindung an den 1. Childprozess (1b)
sprintf(pipeMessage, "%i", newClientConnection[1]);
write(pfds[1], pipeMessage,strlen(pipeMessage));
sleep(1);
clientPid[1] = fork();
// wirf zweiten child aus der schleife
if (getpid() != parentPid) {
break;
}
// uebergib die Verbindungskennung der 2. Verbindung an den 2. Childprozess (2a)
sprintf(pipeMessage, "%i", newClientConnection[1]);
write(pfds[1], pipeMessage,strlen(pipeMessage));
sleep(1);
// uebergib die Verbindungskennung der 1. Verbindung an den 2. Childprozess (2b)
sprintf(pipeMessage, "%i", newClientConnection[0]);
write(pfds[1], pipeMessage,strlen(pipeMessage));
sleep(1);
wait(NULL);
}
// Childprozesse:
if (getpid() != parentPid) {
// uebernehme die eigene Verbindungskennung vom Parentprozess (1a, 2a)
if (read(pfds[0], buf, 9) == -1) {
perror("read");
}
clientFd = atoi(buf);
// uebernehme die Verbindungskennung des Partners vom Parentprozess (1b, 2b)
if (read(pfds[0], buf, 9) == -1) {
perror("read");
}
chatPartnerFd = atoi(buf);
while (1) {
if ((recvStatus = recv(clientFd, messageBuf, MAX_MESSAGE_SIZE - 1,
0)) == -1) {
perror("recv");
exit(1);
}
messageBuf[recvStatus] = '\0';
messageToClient = "Client";
messageToClient.insert(messageToClient.length(), clientId);
messageToClient.insert(messageToClient.length(), ": ");
messageToClient.insert(messageToClient.length(), messageBuf);
sendToClient(chatPartnerFd, messageToClient);
}
close(clientFd);
exit(0);
}
Der Fehler taucht beim letzten sendToClient() auf. Die Funktion sieht uebrigens so aus:
void sendToClient(int sockfd, string message) {
if (send(sockfd, message.c_str(), message.length(), 0) == -1) {
perror("sendToClient");
cout << sockfd << endl;
}
}
Ich weiss, dass die sockfd von Client1 == 6 und die von Client2 == 7 ist.
Der Fehler muss im ersten Childprozess liegen, da der Parent an beide clients senden kann, was ich eben nicht verstehe ist, dass der zweite Child, der ja exakt den selben Code ausfuehrt wie der erste, problemlos senden kann.
Die uebergebene Variablen durch die Pipe von Parent zu Child kommen richtig an.
Waer echt klasse, wenn mir jemand helfen koennte.
Momentan bin ich noch dabei den Server aufzusetzen. Die Kommunikation laeuft ueber Sockets. Der Server hat dabei ein Parentprozess der auf der socket auf Verbindungen wartet.
Meldet sich ein Client, wird ein Childprozess aufgerufen (fork()), der dann die Verbindung abhoert und auf eine receive wartet.
Das ganze soll nur fuer zwei clients funktionieren. Zunaechst blocked der parents also bis zwei clients sich verbunden haben.
Dann wartet der Parentprozess bis die Childprozesse fertig sind.
Die Childprozesse warten jeweils auf ein receive von ihren Verbindungen und senden jenes dann an die jeweilig andere Verbindung.
Jetzt hab ich das verrueckte Problem, dass der erste verbunde Client nachrichten zwar empfangen kann, allerdings keine senden. Der send Befehl meldet jeweils "bad file descriptor". Der spaeter verbundene Client kann aber beides.
Ich post hier mal den code von dem ich denke, dass er die relevanten Stellen zeigt, falls mehr Infos benoetigt werden lasst es mich wissen. Ich waere ueber jede Hilfe dankbar.
// Parentprozess:
while(1) {
sin_size = sizeof(struct sockaddr_in);
// Client1 verbindet
if ((newClientConnection[0] = accept(sockfd,
(struct sockaddr *)&their_addr, &sin_size)) == -1) {
perror("accept");
}
clientPid[0] = fork();
// wirf ersten child aus der schleife
if (getpid() != parentPid) {
break;
}
// uebergib die Verbindungskennung der 1. Verbindung an den 1.Childprozess (1a)
sprintf(pipeMessage, "%i", newClientConnection[0]);
write(pfds[1], pipeMessage,strlen(pipeMessage));
sleep(1);
// Client2 verbindet
if ((newClientConnection[1] = accept(sockfd,
(struct sockaddr *)&their_addr, &sin_size)) == -1) {
perror("accept");
}
// uebergib die Verbindungskennung der 2. Verbindung an den 1. Childprozess (1b)
sprintf(pipeMessage, "%i", newClientConnection[1]);
write(pfds[1], pipeMessage,strlen(pipeMessage));
sleep(1);
clientPid[1] = fork();
// wirf zweiten child aus der schleife
if (getpid() != parentPid) {
break;
}
// uebergib die Verbindungskennung der 2. Verbindung an den 2. Childprozess (2a)
sprintf(pipeMessage, "%i", newClientConnection[1]);
write(pfds[1], pipeMessage,strlen(pipeMessage));
sleep(1);
// uebergib die Verbindungskennung der 1. Verbindung an den 2. Childprozess (2b)
sprintf(pipeMessage, "%i", newClientConnection[0]);
write(pfds[1], pipeMessage,strlen(pipeMessage));
sleep(1);
wait(NULL);
}
// Childprozesse:
if (getpid() != parentPid) {
// uebernehme die eigene Verbindungskennung vom Parentprozess (1a, 2a)
if (read(pfds[0], buf, 9) == -1) {
perror("read");
}
clientFd = atoi(buf);
// uebernehme die Verbindungskennung des Partners vom Parentprozess (1b, 2b)
if (read(pfds[0], buf, 9) == -1) {
perror("read");
}
chatPartnerFd = atoi(buf);
while (1) {
if ((recvStatus = recv(clientFd, messageBuf, MAX_MESSAGE_SIZE - 1,
0)) == -1) {
perror("recv");
exit(1);
}
messageBuf[recvStatus] = '\0';
messageToClient = "Client";
messageToClient.insert(messageToClient.length(), clientId);
messageToClient.insert(messageToClient.length(), ": ");
messageToClient.insert(messageToClient.length(), messageBuf);
sendToClient(chatPartnerFd, messageToClient);
}
close(clientFd);
exit(0);
}
Der Fehler taucht beim letzten sendToClient() auf. Die Funktion sieht uebrigens so aus:
void sendToClient(int sockfd, string message) {
if (send(sockfd, message.c_str(), message.length(), 0) == -1) {
perror("sendToClient");
cout << sockfd << endl;
}
}
Ich weiss, dass die sockfd von Client1 == 6 und die von Client2 == 7 ist.
Der Fehler muss im ersten Childprozess liegen, da der Parent an beide clients senden kann, was ich eben nicht verstehe ist, dass der zweite Child, der ja exakt den selben Code ausfuehrt wie der erste, problemlos senden kann.
Die uebergebene Variablen durch die Pipe von Parent zu Child kommen richtig an.
Waer echt klasse, wenn mir jemand helfen koennte.