jenya7 0 13 сентября, 2017 Опубликовано 13 сентября, 2017 · Жалоба Пишу на vxWorks но наверно это не важно. Принцип везде одинаков. Создаю сокет и пытаюсь подключиться к серверу. Сервером выступает компьютер. На компьютере запускаю Hercules -> TCP Server -> Port 8200 (SERVER_PORT_NUM) -> Listen. Сервер бежит. На стороне прибора STATUS TCP_ClientConnect (char *serverName, int *soc_desc) { struct sockaddr_in serverAddr; /* server's socket address */ int sockAddrSize; /* size of socket address structure */ int sFd; /* socket file descriptor */ /* create client's socket */ if ((sFd = socket (AF_INET, SOCK_STREAM, 0)) == ERROR) { //perror ("socket"); printf ("SOCKET ERROR\n"); return (ERROR); } /* bind not required - port number is dynamic */ /* build server socket address */ sockAddrSize = sizeof (struct sockaddr_in); bzero ((char *) &serverAddr, sockAddrSize); serverAddr.sin_family = AF_INET; serverAddr.sin_len = (u_char) sockAddrSize; serverAddr.sin_port = htons (SERVER_PORT_NUM); if (((int)(serverAddr.sin_addr.s_addr = inet_addr (serverName)) == ERROR) && ((int)(serverAddr.sin_addr.s_addr = hostGetByName (serverName)) == ERROR)) { printf ("UNKNOWN SERVER NAME\n"); close (sFd); return (ERROR); } /* bind a port number to the socket */ if (bind(sFd, (struct sockaddr *) &serverAddr, sizeof(serverAddr)) == ERROR) { printf("BIND ERROR\n"); return (ERROR); } /* connect to server */ if (connect (sFd, (struct sockaddr *) &serverAddr, sockAddrSize) != OK) { printf ("CONNECTION ERROR\n"); close (sFd); return (ERROR); } *soc_desc = sFd; return (OK); } И запускаю таск int socket_descriptor=0; char *server_ip = "10.0.0.80"; void tSpectraTaskEntryPoint() { if (TCP_ClientConnect(server_ip, &socket_descriptor)==ERROR) printf ("CLIENT CONNECT ERROR\n"); else printf("CLIENT CONNECT OK descriptor = %d\n", socket_descriptor); SpectraMain(); } Получаю ошибку BIND ERROR CLIENT CONNECT ERROR Значит не выполняется привязка сокета к серверу? Я что то не так делаю? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jenya7 0 13 сентября, 2017 Опубликовано 13 сентября, 2017 (изменено) · Жалоба модифицировал функцию чтоб выводить информацию. STATUS TCP_ClientConnect (char *serverName, int *soc_desc) { struct sockaddr_in serverAddr; /* server's socket address */ int sockAddrSize; /* size of socket address structure */ int sFd; /* socket file descriptor */ /* create client's socket */ if ((sFd = socket (AF_INET, SOCK_STREAM, 0)) == ERROR) { printf ("SOCKET ERROR\n"); return (ERROR); } else printf ("SOCKET DESC = %d\n", sFd); /* bind not required - port number is dynamic */ /* build server socket address */ sockAddrSize = sizeof (struct sockaddr_in); bzero ((char *) &serverAddr, sockAddrSize); serverAddr.sin_family = AF_INET; serverAddr.sin_len = (u_char) sockAddrSize; serverAddr.sin_port = htons (SERVER_PORT_NUM); if (((int)(serverAddr.sin_addr.s_addr = inet_addr (serverName)) == ERROR) && ((int)(serverAddr.sin_addr.s_addr = hostGetByName (serverName)) == ERROR)) { printf ("UNKNOWN SERVER NAME\n"); close (sFd); return (ERROR); } else { printf ("ADDR = %d\n", serverAddr.sin_addr.s_addr); printf ("PORT = %d\n", serverAddr.sin_port); } /* bind a port number to the socket */ if (bind(sFd, (struct sockaddr *) &serverAddr, sizeof(serverAddr)) == ERROR) { printf("BIND ERROR\n"); return (ERROR); } /* connect to server */ if (connect (sFd, (struct sockaddr *) &serverAddr, sockAddrSize) != OK) { printf ("CONNECTION ERROR\n"); close (sFd); return (ERROR); } *soc_desc = sFd; return (OK); } вижу SOCKET DESC = 26 ADDR = 1342177290 PORT = 2080 BIND ERROR CLIENT CONNECT ERROR перевожу 1342177290 в ИП аддресс получается 80.0.0.10 - перевернутый. порт тоже - вместо 8200 - 2080. Изменено 13 сентября, 2017 пользователем Jenya7 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Des333 0 13 сентября, 2017 Опубликовано 13 сентября, 2017 · Жалоба перевожу 1342177290 в ИП аддресс получается 80.0.0.10 - перевернутый. порт тоже - вместо 8200 - 2080. И какой вывод можно получить? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
gerber 8 13 сентября, 2017 Опубликовано 13 сентября, 2017 · Жалоба Клиентский сокет можно не bind-ить, так как порт выделяется динамически, у вас же это и написано в комментариях. bind на клиенте нужен, если вы хотите привязать сокет к конкретному локальному интерфейсу и порту. У вас же идет bind к удаленному адресу и порту, что, конечно же, ни в какие ворота... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jenya7 0 13 сентября, 2017 Опубликовано 13 сентября, 2017 (изменено) · Жалоба Клиентский сокет можно не bind-ить, так как порт выделяется динамически, у вас же это и написано в комментариях. bind на клиенте нужен, если вы хотите привязать сокет к конкретному локальному интерфейсу и порту. У вас же идет bind к удаленному адресу и порту, что, конечно же, ни в какие ворота... но я хочу чтоб сокет обращался к серверу по его IP - 10.0.0.80 И порту 8200. Я не должен указать сокету куда обращаться? Это какой то бродкаст получается. убрал байндинг и заработало. проверяю void SpectraMain() { while (spectra_alive) { if (TCP_ClientRead(read_buf, socket_descriptor) != ERROR) { printf ("CLIENT RECIEVED MESSAGE\n"); //echo back TCP_ClientWrite(read_buf, socket_descriptor); } else { TCP_ClientWrite("no message", socket_descriptor); } taskDelay(50); } } на Hercules -> TCP Server посылаю строку - получаю CLIENT RECIEVED MESSAGE + строку. спасибо. Изменено 13 сентября, 2017 пользователем Jenya7 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
gerber 8 13 сентября, 2017 Опубликовано 13 сентября, 2017 · Жалоба но я хочу чтоб сокет обращался к серверу по его IP - 10.0.0.80 И порту 8200. Я не должен указать сокету куда обращаться? Это какой то бродкаст получается. В это невозможно поверить, но для этого есть функция connect() Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jenya7 0 14 сентября, 2017 Опубликовано 14 сентября, 2017 (изменено) · Жалоба Тут возникает такой вопрос. Если связь с сервером прервалась? Что делать? Периодически проверять связь с сервером? А сокет? Он жив пока его не закрыли? Или надо проверять и его? Изменено 14 сентября, 2017 пользователем Jenya7 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Eddy_Em 1 14 сентября, 2017 Опубликовано 14 сентября, 2017 · Жалоба Все надо проверять. Здесь я намучился с этими чертовыми сокетами! Сокет - не файл, запись в закрытый с другой стороны сокет никаких ошибок не даст! Поэтому нужно вводить таймауты и/или периодические рукопожатия. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jenya7 0 14 сентября, 2017 Опубликовано 14 сентября, 2017 · Жалоба Все надо проверять. Здесь я намучился с этими чертовыми сокетами! Сокет - не файл, запись в закрытый с другой стороны сокет никаких ошибок не даст! Поэтому нужно вводить таймауты и/или периодические рукопожатия. я понял. а как проверять? периодически делать if (connect (sFd, (struct sockaddr *) &serverAddr, sockAddrSize) != OK) или можно как то более красиво? а сокет как проверить? if (socket_descriptor != 0) ? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Сергей Борщ 136 14 сентября, 2017 Опубликовано 14 сентября, 2017 · Жалоба Все уже придумано за нас. Почитайте про SO_KEEPALIVE. Там по умолчанию довольно большие таймауты, но вы можете установить свои. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jenya7 0 14 сентября, 2017 Опубликовано 14 сентября, 2017 (изменено) · Жалоба Все уже придумано за нас. Почитайте про SO_KEEPALIVE. Там по умолчанию довольно большие таймауты, но вы можете установить свои. нашел такой пример /* Set the option active */ optval = 1; optlen = sizeof(optval); if(setsockopt(s, SOL_SOCKET, SO_KEEPALIVE, &optval, optlen) < 0) { perror("setsockopt()"); close(s); exit(EXIT_FAILURE); } printf("SO_KEEPALIVE set on socket\n"); это чтоб включить SO_KEEPALIVE. компилируется без ошибок. а как теперь проверить жив сокет или нет? я так понимаю с выставленной опцией где то бежит проверка каждые tcp_keepalive_intvl и наверно выставляется флаг гдето в статусном регистре, который надо проверять. The SO_KEEPALIVE option causes a packet (called a 'keepalive probe') to be sent to the remote system if a long time (by default, more than 2 hours) passes with no other data being sent or received. This packet is designed to provoke an ACK response from the peer. This enables detection of a peer which has become unreachable (e.g. powered off or disconnected from the net). а где я вижу этот ACK response from the peer? Все надо проверять. Здесь я намучился с этими чертовыми сокетами! Сокет - не файл, запись в закрытый с другой стороны сокет никаких ошибок не даст! Поэтому нужно вводить таймауты и/или периодические рукопожатия. у меня этот код компилируется. static int waittoread(int sock){ fd_set fds, efds; struct timeval timeout; int rc; timeout.tv_sec = 1; // wait not more than 1 second timeout.tv_usec = 0; FD_ZERO(&fds); FD_ZERO(&efds); FD_SET(sock, &fds); FD_SET(sock, &efds); do{ rc = select(sock+1, &fds, NULL, &efds, &timeout); if(rc < 0){ if(errno != EINTR){ putlog("Server not available"); WARN("select()"); return -1; } continue; } break; }while(1); if(FD_ISSET(sock, &efds)) return -1; // exception - socket closed if(FD_ISSET(sock, &fds)) return 1; return 0; } это значит так можно проверить и сервер и сокет? Изменено 14 сентября, 2017 пользователем Jenya7 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Сергей Борщ 136 14 сентября, 2017 Опубликовано 14 сентября, 2017 · Жалоба а как теперь проверить жив сокет или нет?Он закроется, а дальше write() и read() будут возвращать ноль - это и будет признаком того, что соединение разорвано. Кажется так. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jenya7 0 14 сентября, 2017 Опубликовано 14 сентября, 2017 (изменено) · Жалоба Он закроется, а дальше write() и read() будут возвращать ноль - это и будет признаком того, что соединение разорвано. Кажется так. допустим сервер не посылает мне ничего но соединение живо. в read() я получу 0 но это может быть потому что сервер ничего не послал. я думаю есть какие то статусные биты которые говорят что соединение разорвано. делаю так #if KEEPALIVE_ON /* Set the option active */ optval = 1; optlen = sizeof(optval); if(setsockopt(sFd, SOL_SOCKET, SO_KEEPALIVE, &optval, optlen) < 0) { close(sFd); return (ERROR); } printf("SO_KEEPALIVE set on socket\n"); /* Interval (in seconds) between keepalives */ optval = 1; setsockopt(sFd, IPPROTO_TCP, TCP_KEEPINTVL, &optval, optlen); /* Maximum number of keepalives before dropping the connection */ optval = 10; setsockopt(sFd, IPPROTO_TCP, TCP_KEEPCNT, &optval, optlen); /* Send first keepalive probe when the connections been idle this time (in seconds) */ optval = 5; setsockopt(sFd, IPPROTO_TCP, TCP_KEEPIDLE, &optval, optlen); #endif теперь по идее мы должны иметь какую то индикацию, статус соединения. Изменено 14 сентября, 2017 пользователем Jenya7 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
gerber 8 14 сентября, 2017 Опубликовано 14 сентября, 2017 · Жалоба Если удаленный сервер корректно закрыл TCP-соединение, то на стороне клиента попытка записи-чтения должна возвращать ошибку "Bad file descriptor" или что-то в этом духе. Хотя зависит от реализации стека, вероятно. Гораздо сложнее история, если разрыв соединения произошел внезапно и физически (выдернули кабель). Тут или мудрить с keep-alive, или самостоятельно реализовывать логику закрытия сокета при неполучении ответа от сервера в то или иное время. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jenya7 0 14 сентября, 2017 Опубликовано 14 сентября, 2017 · Жалоба Если удаленный сервер корректно закрыл TCP-соединение, то на стороне клиента попытка записи-чтения должна возвращать ошибку "Bad file descriptor" или что-то в этом духе. Хотя зависит от реализации стека, вероятно. Гораздо сложнее история, если разрыв соединения произошел внезапно и физически (выдернули кабель). Тут или мудрить с keep-alive, или самостоятельно реализовывать логику закрытия сокета при неполучении ответа от сервера в то или иное время. а код от Эдди static int waittoread(int sock){ fd_set fds, efds; struct timeval timeout; int rc; timeout.tv_sec = 1; // wait not more than 1 second timeout.tv_usec = 0; FD_ZERO(&fds); FD_ZERO(&efds); FD_SET(sock, &fds); FD_SET(sock, &efds); rc = select(sock+1, &fds, NULL, &efds, &timeout); if(rc < 0) { putlog("Server not available"); return -1; } break; if(FD_ISSET(sock, &efds)) return -1; // exception - socket closed if(FD_ISSET(sock, &fds)) return 1; return 0; } разве он не проверяет все случаи? там и сервер и сокет проверяется. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться