我需要帮助。我为我糟糕的英语道歉。我希望能够解释我的问题。 我在C Unix中编写了一个客户端/服务器程序。 服务器是多线程的。 在服务器开始操作文件之前,我没有遇到任何问题。 但要小心,因为真正的问题不在于文件操作:服务器操作文件没有问题。它可以多次打开和关闭这些文件,并可以顺利读写。 真正的问题:当使用操作文件的服务的客户端断开连接或者当前一个客户端使用文件操作服务时新客户端是否想要连接时,服务器接受连接,启动pthread_create函数但是这无法完成新线程的创建。然后不执行启动功能。我已经意识到这种行为,因为pthread_join返回错误“invalid argument”,我的启动函数不会打印“SERVER:New Thread created!”并且相同的pthread_create NOT会返回错误的“值> 0”。 我想澄清一下,当服务器启动时以及启动任意数量的客户端后,一切正常。但是只要一个客户端调用操作文件的服务,服务器就无法完成pthread_create功能。 为什么是这样?我是天,我试着了解会发生什么。谁帮助我? 这是创建新线程的函数:
void gestisciConnessioni(int serverfdin, int numeroconnessioniIn, struct sockaddr_in *clientindirizzoin, int *connessioneclientin) {
//Variabile/i locale/i:
struct sockaddr *clientindirizzoptr; //Puntatore alla Struttura indirizzo del client
int clientindirizzodim; //Dimensione dell'indirizzo del client
char *indirizzoip;
tipoinfoconnessioneclient *unainfoclient = NULL;
pthread_t tid;
int errore = -1;
//Blocco codice:
//Il server si mette in ascolto dei clients:
if ((listen(serverfdin, numeroconnessioniIn)) != 0) {
printf("SERVER: Attenzione, listening... fallito!\n");
exit(1);
}
//Preparazione indizzamento client:
clientindirizzoptr = (struct sockaddr *) clientindirizzoin;
clientindirizzodim = sizeof ((*clientindirizzoin));
//Inizio concorrenza:
//Il Server accetta la connessione del client;
//Verifica la presenza di errori;
//Inizia l'elaborazione.
while (1) {
*connessioneclientin = accept(serverfdin, clientindirizzoptr, &clientindirizzodim);
if ((*connessioneclientin) > -1) {
indirizzoip = inet_ntoa((*clientindirizzoin).sin_addr);
printf("SERVER: Nuova connessione stabilita con %s.\n", indirizzoip);
unainfoclient = (tipoinfoconnessioneclient *) (malloc(sizeof (tipoinfoconnessioneclient)));
(*unainfoclient).descrittorefile = *connessioneclientin;
(*unainfoclient).indirizzoip = indirizzoip;
errore = pthread_create(&tid, NULL, elaborazioneServizi, (void *) (unainfoclient));
if (errore != 0) {
printf("SERVER: Impossibile creare un nuovo thread!\n");
printf("(SERVER, ERRORE: %s)\n", strerror(errore));
exit(1);
}
pthread_detach(tid);
errore = pthread_join(tid, NULL);
if (errore != 0) {
printf("SERVER: Impossibile attendere la terminazione del thread!\n");
printf("(SERVER, ERRORE: %s)\n", strerror(errore));
exit(1);
}
} else {
printf("SERVER: Attenzione, connessione con %s... fallita!\n", indirizzoip);
exit(1);
}
}
}
这是启动功能:
void *elaborazioneServizi(void *args) {
//Varibile/i locale/i:
tipoinfoconnessioneclient unainfo;
tipoinfoutente giocatore;
int n;
char messaggioin[100];
char **messaggioSplittato = NULL;
int risposta = 0;
int scelta = -1;
fd_set insiemelettura;
int fdmassimo;
//Blocco codice:
unainfo = *((tipoinfoconnessioneclient *) args);
//**************************************************************************
//Inizializzazione giocatore:
//**************************************************************************
giocatore.ip = unainfo.indirizzoip;
giocatore.nome = " ";
giocatore.stato = 2;
giocatore.ultimaposizione.x = -1;
giocatore.ultimaposizione.y = -1;
//**************************************************************************
printf("SERVER: Sto dentro la funzione di avvio!\n");
fdmassimo = unainfo.descrittorefile;
FD_SET(unainfo.descrittorefile, &insiemelettura);
printf("SERVER: Nuovo Thread appena creato!\n");
select(fdmassimo + 1, &insiemelettura, NULL, NULL, NULL);
while (risposta == 0) {
if (FD_ISSET(unainfo.descrittorefile, &insiemelettura)) {
//*****************************************************************
if ((n = read(unainfo.descrittorefile, messaggioin, 100)) == -1) {
printf("SERVER: Errore in ricezione messaggio!\n");
exit(1);
}
while (n == 0) {
pthread_cond_wait(&condizione, &mutex);
}
pthread_cond_signal(&condizione);
printf("SERVER: Messaggio ricevuto per SWICTH: %s\n", messaggioin);
messaggioSplittato = messaggioAvettore(messaggioin, 5, 50);
scelta = atoi(messaggioSplittato[0]);
switch (scelta) {
case 0:
daiUscita(unainfo.descrittorefile, &risposta);
break;
case 1:
daiRegistrazione(unainfo.descrittorefile, messaggioSplittato);
break;
case 2:
daiLogin(unainfo.descrittorefile, messaggioSplittato);
break;
default:
printf("SERVER: Servizio, non disponibile!\n");
risposta = 1;
break;
}
//*****************************************************************
}
}
printf("SERVER: Thread... eliminato!\n");
close(unainfo.descrittorefile);
pthread_exit(NULL);
}
这是执行file.txt(其中最短的)操作的函数:
void daiLogin(int canalecomunicazionein, char **messaggioin) {
//Variabile/i locale/i:
int dimensionemessaggio = (NICKNAME_DIMENSIONE + PASSWORD_DIMENSIONE) + 2;
char *nomeutente = NULL;
char *password = NULL;
char messaggioletto[NICKNAME_DIMENSIONE + PASSWORD_DIMENSIONE];
char **messaggiosplittato = NULL;
char *stringaconvalidata = NULL;
char *messaggioout = NULL;
char tmp[3];
int trovato = 0; //Trovato indica un utente registrato (1) oppure da registrare (0)
int *fd = NULL;
int n = -1;
//Blocco codice:
pthread_mutex_lock(&mutex);
printf("SERVER: Sto eseguendo la funzione daiLogin()\n");
nomeutente = messaggioin[1];
password = messaggioin[2];
printf("SERVER: (%s,%s)\n", nomeutente, password);
fd = inizializzaFileInLettura("registrazioni.txt");
if (*fd != -1) {
lseek(*fd, 0, SEEK_SET);
while ((n = read(*fd, messaggioletto, dimensionemessaggio))&&(trovato == 0)) {
messaggiosplittato = messaggioAvettore(messaggioletto, 3, dimensionemessaggio);
if ((strcmp(messaggiosplittato[0], nomeutente) == 0)&&(strcmp(messaggiosplittato[1], password) == 0)) {
trovato = 1;
}
free(messaggiosplittato);
messaggiosplittato = NULL;
}
close(*fd);
free(fd);
fd = NULL;
snprintf(tmp, sizeof (tmp), "%d", trovato);
messaggioout = componiMessaggio(tmp, "X", "X", "X", "X", 10);
n = write(canalecomunicazionein, messaggioout, 10);
pthread_mutex_unlock(&mutex);
}
}
pthread_create不出错误/ s。只有错误来自pthread_join 说“无效论证”。我使用一个始终打开的FD(仅) 并且关闭(每次)。
答案 0 :(得分:2)
在致电pthread_join
后,您无法pthread_detach
。线程pthread_detach
确保您不必{且不允许pthread_join
它。
pthread_create
然后紧跟pthread_join
后感觉有点无意义。你可以自己调用这个函数,省去自己的努力。
此处有缓冲区溢出:read(*fd, messaggioletto, dimensionemessaggio)
此处FD_SET(unainfo.descrittorefile, &insiemelettura);
insi...
变量未初始化。说到select
,现代代码根本不应该使用select
。特别是因为你的线程必须意味着你期待很多联系。这意味着您将超出fd_set
的隐藏限制,通常为1024 fds。请改用poll
。
在daiLogin
中你锁定了一些互斥锁,但是当if (*fd != -1) {
为false时你没有解锁它。我敢打赌,这是你认为pthread_create
失败的实际原因。 pthread_create
没有失败,只是你的线程没有打印任何东西,因为互斥锁已被锁定而pthread_join
失败,因为线程被分离了。
答案 1 :(得分:1)
您无法加入 分离的主题。
来自人pthread_detach
:
分离线程后,无法将其与
pthread_join
(3)连接或再次连接。