2015-12-30 1 views
0

Я нашел некоторый код в Интернете с некоторыми основами о создании сервера TCP/IP на C++. Я взял этот код, добавил некоторые библиотеки и некоторые строки кода. В результате я могу скомпилировать и запустить код/​​сервер в Qt Creator в Windows в качестве консольной программы. Тем не менее я не могу подключиться к серверу, потому что он просто проходит через код, не дожидаясь и не получая соединение от клиента TCP.Сервер TCP/IP в C++ не ждет клиента

Это код: EDIT: Код обновлен, и теперь он работает. Тест против == -1 - это решение.

#define PORT 2000 
#define MAX_QUEUE 5 
#define BUF_SIZE 1024 

int main(int argc, char* const argv[]) 
{ 
cout << "Hello World!" << endl;  
     WSADATA wsaData; 
int wsaret = WSAStartup(MAKEWORD(4, 4), &wsaData); 
cout << "wsaret: " << wsaret << endl; 

cout << "Start TCP/IP Server" << endl; 

/* file descriptors for sockets */ 
SOCKET sock_1, sock_2; //switched from in to SOCKET //unsigned int sock_1, sock_2; 
int rec_value, length; 
char buf[BUF_SIZE]; 

//struct sockaddr_in server; 
struct sockaddr_in server; 

/* create stream socket in internet domain*/ 
sock_1 = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP); 
//if(sock_1 < 0) 
if(sock_1 == -1) 
{ 
    cout << "socket: " << WSAGetLastError() << endl; //instead of //cout << "socket: " << strerror(errno) << endl; //cout << "socket wsaret: " << wsaret << endl; 
    exit(1); 
} 

/* build address in internet domain */ 
server.sin_family = AF_INET; 

/* everyone is allowed to connet to server */ 
server.sin_addr.s_addr = INADDR_ANY; //inet_addr("192.168.145.129"); 
server.sin_port = htons(2000); //server.sin_port = PORT; //Port: 2000 

/* bind socket */ 
//if(bind(sock_1, (struct sockaddr *)&server, sizeof(server))); 
int bindreturn = (bind(sock_1, (struct sockaddr *)&server, sizeof(server))); 
if(bindreturn == -1) 
{ 
    cout << "bind: " << WSAGetLastError() << endl; //instead of //cout << "bind: " << strerror(errno) << endl; //cout << "bind wsaret: " << wsaret << endl; 
    exit(1); 
} 

listen(sock_1,MAX_QUEUE); 
    /* start accepting connection */ 
    sock_2 = accept(sock_1,0,0); 
    if(sock_2 < 0) 
    { 
     cout << "accept: " << WSAGetLastError() << endl; 
     exit(1); 
    } 

    /* read from sock_2 */ 
    while(rec_value=recv(sock_2,buf,BUF_SIZE,0)) 
    { 
     if(rec_value < 0) 

     { 
     cout << "recv: " << WSAGetLastError() << endl; 
     exit(1); 
     } 
     else 
     { 
      cout << "else" << endl; 
      send(sock_2,"1,2,3",strlen("1,2,3"),0); 
     } 
    } 

    cout << "Ending connection" << endl; 
    closesocket(sock_1); 
    closesocket(sock_2); 
    cout << "End TCP/IP Server" << endl; 

    WSACleanup(); 
return 0; 
} 

Консоль показывает следующее после/во время выполнения программы в одном или менее секунд:

Hello World! 
wsaret: 0 
Start TCP/IP Server 
bind: 0 

Что я могу сделать, что сервер ожидает партнера соединения?

Заранее спасибо.

С уважением MATL

Edit: Добавлено несколько строк кода в начале, что я забыл раньше. Редактировать: Код обновления Редактировать: Код обновления

+0

Не похоже, что вы включили весь код? Для начала, часть, где «Hello World!» строка не включена в код. Может быть, если бы вы включили полный код, будет легче увидеть, что пошло не так? Кроме того, если мне угрожать догадки, я бы сказал, что вам нужно включить аргументы командной строки в порт связывания и т. Д. При запуске фактического исполняемого файла. – Liang

+2

Поскольку сбой 'bind' не выполняется, любая последующая операция также завершится с ошибкой. Скорее всего, вероятно, что другой процесс уже прослушивает порт. Проверьте 'errno', чтобы определить, что пошло не так. – molbdnilo

+0

Вы сообщаете об ошибках, а затем игнорируете их полностью и продолжаете, как будто их не было. Ошибка прослушивания или привязки * фатальная. * Ничто не может работать после. И просто печать -1 тоже неприемлема. Вы должны напечатать * ошибку, * через 'perror()' или 'strerror()'. Не пишите такой код. – EJP

ответ

2

Я собираюсь прокомментировать подробный исходный код, который вы опубликовали.

cout << "Start TCP/IP Server" << endl; 

//int sock_1,sock_2;  /* file descriptors for sockets */ 
int sock_1, sock_2; 
int rec_value, length; 
char buf[BUF_SIZE]; 

//struct sockaddr_in server; 
sockaddr_in server; 

/* create stream socket in internet domain*/ 
sock_1 = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);//0); 

Отсутствует тест здесь.Вы должны проверить результат на -1 вдоль этих линий:

if (sock_1 == -1) 
{ 
    cout << "socket creation error: " << WSAGetLastError() << endl; 
    exit(1); // or some other measure to prevent continuation 
} 

Назад к коду:

/* build address in internet domain */ 
server.sin_family = AF_INET; 

/* everyone is allowed to connet to server */ 
server.sin_addr.s_addr = INADDR_ANY; //inet_addr("192.168.145.129"); 
server.sin_port = PORT; //Port: 2000 

Это должно быть

server.sin_port = htons(PORT); 

Назад к коду:

/* bind socket */ 
int bindreturn = bind(sock_1, (struct sockaddr *)&server, sizeof(server)); 
cout << "bindreturn: " << bindreturn << endl; 

Недостаточно. Здесь снова вам нужно проверить значение -1 и распечатать WSAGetLastError() и выйти, если вы его получили.

listen(sock_1,MAX_QUEUE); 

Непрошеный. Здесь снова вам нужно проверить на -1 и т. Д.

/* start accepting connection */ 
    //system("pause"); 
    sock_2 =accept(sock_1,0,0); 
    //system("pause"); 
    cout << "acceptreturn: " << sock_2 << endl; 

Неадекватный снова, см. Выше.

/* read from sock_2 */ 
    while(rec_value=recv(sock_2,buf,BUF_SIZE,0)) 
    { 
     if(rec_value<0) 
     { 
     cout << "error: " << rec_value << endl; 
     exit(1); 
     } 

Тестирование неверно. Системный вызов указывает ошибку, возвращая ровно -1, а не только любое значение < 0. Сокет FD, например, возвращенный socket() или accept(), может быть отрицательным или любым значением, отличным от -1.

 else 
     { 
      cout << "else" << endl; 
      send(sock_2,"1,2,3",strlen("1,2,3"),0); 
     } 
    } 
closesocket(sock_1); 
closesocket(sock_2); 

cout << "End TCP/IP Server" << endl; 

return 0; 

Это видно из closesocket() вызовов, которые вы используете Winsock, в этом случае как WSAStart() и WSACleanup() пропали без вести.

2

0 Как есть PORT?

Вы должны использовать:

server.sin_port = htons(PORT); //Port: 2000 

Ваш IP-адрес правильно?

Все ваши звонки получают SOCKET_ERROR (-1), поэтому вам нужно проверить lasterror, чтобы получить дополнительную информацию.

Не уверен (на Windows здесь), но не должно быть unsigned int?

int sock_1, sock_2; 

Update:

Хорошо, вы, кажется, использует Qt на Windows.

Для Qt вы также можете использовать Qt libraries.

В Windows в целом вы можете использовать бесплатную MS Visual Studio.

Вы также должны позвонить WSAStartup() так:

WSADATA wsaData; 
int wsaret = WSAStartup(MAKEWORD(4, 4), &wsaData); 
// check wsaret 

// more code here 

WSACleanup(); 

Также используйте SOCKET:

SOCKET sock_1, sock_2; 

Проверьте правильность errorcodes с WSAGetLastError().

+0

Я создаю небольшую консольную программу на C++ с Qt Creator без Qt в ней на машине Windows. Если я не ошибаюсь "server.sin_addr.s_addr = INADDR_ANY;" allwos каждый IP-адрес. Я использую «server.sin_port = htons (2000)»; теперь, но bind() все еще не работает. – matl

+0

@matl - как далеко вы получаете новый код? Кроме того, не забудьте 'htons (PORT)'. Также проверьте код возврата из listen(). И ваш'accept() 'нуждается в лучших параметрах. –

+0

Вы используете winsock2? (вам может понадобиться SOCKET вместо int). Или любые библиотеки Qt? Потому что код, который вы нашли, почти наверняка написан для Linux. Какие заголовки вы включаете? –

Смежные вопросы