в связи с тупиком немного отошел просто от темы, поэтому не был тут два дня, значит так, к настоящему моменту, дописал небольшой кусок, который пытается заблокировать сокет, если блокируется, переходит сразу к получению сообщения, если нет, вызывается select и потом опять же к принятию сообщения, при подключении 1-го клиента все происходит нормально, сокет пишет, что заблокирован и запросы обрабатываются, когда подключается второй клиент, то заблокировать сокет не удается и вызывается select, в который все и уходит с концами, при наличии отправленных сообщений от клиента,
кусок кода отвечающий за создание нового процесса выглядит так:
printf ("INFO: listener ... \n");
int ident, res, flag;
thread_arg *arg;
ident = list.AddNode ();
arg = list.GetRecord (ident);
if (arg == 0) {
printf ("[ERROR] Create Node for new thread!\n");
// ~~~~~!!!!!~~~~~
}
arg->_listener = listener;
arg->_sock = accept (listener, (struct sockaddr*)&(arg->_addr), &(arg->_len));
flag = fcntl (arg->_sock, F_GETFL);
fcntl (arg->_sock, F_SETFL, flag & (~O_NONBLOCK));
flag = fcntl (arg->_sock, F_GETFL);
if (flag & O_NONBLOCK) printf ("Yes\n");
printf ("%-6d %-15s:%-4d\n", ident, inet_ntoa(arg->_addr.sin_addr), ntohs(arg->_addr.sin_port));
arg->ident = ident;
res = pthread_create(&(arg->thread), 0, thread_server, arg);
if (res != 0) {
perror("pthread_create");
close (arg->_sock);
//printf ("pthrres != 0\n");
// ~~~~~!!!!!~~~~~
} else {
printf ("INFO: New thread has been created ...\n");
}
list.UNLockMutex(ident);
кусок кода внутри созданного процесса, отвечающий за начало работы:
FD_ZERO (&rfds);
FD_SET (ARG->_sock, &rfds);
FD_ZERO (&afds);
FD_SET (ARG->_sock, &afds);
flag = fcntl (ARG->_sock, F_GETFL);
fcntl (ARG->_sock, F_SETFL, flag & (~O_NONBLOCK));
flag = fcntl (ARG->_sock, F_GETFL);
if (flag & O_NONBLOCK) {
printf ("Yes0\n");
if (select (2, &rfds, 0, 0, 0) < 0) {
perror("thread select");
//pthread_cleanup_pop(1);
pthread_exit(arg);
return 0;
}
printf ("select getten\n");
} else printf ("No0\n");
if (recvall (ARG->_sock, ARG->_user, 64, 0) == -1) printf ("!!ERROR!! recv returned -1\n");
//puts ("\e[1;33;4;44m");
printf ("%s", ARG->_user);
//puts ("\e[0m");
printf (": logon (%u thread)\n", ARG->ident);
//pthread_testcancel();
while (cycle) {
printf ("%d: while ... ", ARG->ident);
fflush (stdout);
flag = fcntl (ARG->_sock, F_GETFL);
fcntl (ARG->_sock, F_SETFL, flag & (~O_NONBLOCK));
flag = fcntl (ARG->_sock, F_GETFL);
if (flag & O_NONBLOCK) {
printf ("Yes1\n");
FD_ZERO(&rfds);
memcpy (&rfds, &afds, sizeof(afds));
if (select (2, &rfds, 0, 0, 0) < 0) {
perror("thread select");
//pthread_cleanup_pop(1);
break;
//return 0;
}
printf ("select getten\n");
} else printf ("No1\n");
recvall (ARG->_sock, (char*)&ihead, sizeof(struct head_of_packages_info), 0);
/// дальше код анализа
}
код функции recvall:
int recvall (int s, char *buf, int len, int flags) {
int total = 0;
int n;
while(total < len) {
errno = 0;
n = recv(s, buf+total, len - total, flags);
if(n == -1) { break; }
total += n;
}
//printf ("s = %d total = %d n = %d errno = %d\n", s, total, n, errno);
return (n==-1 ? -1 : total);
}
вывод сообщений сервера:
INFO: connection has been gotten ...
INFO: listener ...
1 0.0.0.0 :0
INFO: New thread has been created ...
No0
client: logon (1 thread)
1: while ... No1
recieved
1: Create ...
1: while ... No1
recieved
1: Exit ... type = 3072
client: logoff (by 1 thread)
INFO: connection has been gotten ...
INFO: unlist ...
INFO: input == THREAD_EXIT
INFO: Thread ident = (real 1 / arg 1) from (amount = 1 / max = 1) threads has been exited
INFO: connection has been gotten ...
INFO: listener ...
1 127.0.0.1 :37277
INFO: New thread has been created ...
No0
qwerty: logon (1 thread)
1: while ... No1
recieved
1: Create ...
1: while ... No1
recieved
1: Clean ...
1: while ... No1
INFO: connection has been gotten ...
INFO: listener ...
Yes
2 193.13.2.0 :0
INFO: New thread has been created ...
Yes0
как можно видеть, сначала подключается клиент "client", успешно проводит операции и отключается, потом подключается другой клиент "qwerty", проводит операции, приостанавливает операции (ну просто консольный клиент в другом окне запущен, смысла особого что-то вводить нет, но все запросы выполняются, если ввести), но не отключается, теперь подключается еще один клиент, т.к. теперь одновременно два клиента, то первая цифра в сообщениях, отвечающая за то, кто сделал запрос, становится 2, основной сервер выводит, что поток создан, а потом уже сам поток выводит сообщение о том, что сокет не заблокирован, из того куска кода который выше, переходит потом как по коду видно в селект и зависает, хотя на входе есть сообщения от подключившегося клиента. кстати да, тут на листинге видна ошибка определения ip адресов, хотя клиент подключался всегда через петлю, т.е. 127.0.0.1, использование внешнего ip ситуацию не меняет.
данный листинг работы программы продемонстрирован с целью показать, что если клиенты работают поочереди (т.е. новый не подключается, пока уже подключившийся не отключится), то проблем не возникает.