PDA

Просмотр полной версии : Помогите разобратся с сокет сервером на С++


malik555
21.06.2009, 12:41
Всем привет !

Написал сокет сервер на с++ незнаю правельно или нет - но так работает и запросы принемает , проблема в том что я не как не могу ответить клиенту через функцию send() ,



int main ( )
{
int sockfd,client;
sockfd = socket(PF_INET, SOCK_STREAM, 0);
socklen_t n;


struct sockaddr_in addr;
bzero(&addr, sizeof(addr));

addr.sin_family = AF_INET;
addr.sin_port = htons(5190);
addr.sin_addr.s_addr = htonl(INADDR_ANY);



if(bind(sockfd,(struct sockaddr *) &addr, sizeof(addr)) != -1){

cout << "SERVER - STARTED !!!" <<"\n";
while(1) {
if(!listen(sockfd, 5)){

n = sizeof(addr);
if((client = accept(sockfd, (struct sockaddr *) &addr, &n)) != -1){
cout << "Coonect-" <<inet_ntoa(addr.sin_addr) <<"\n";

char c;
bool finished;
char buffer[1024];
finished = read(client, &c, 10);
cout << client << "---" << c <<"\n";

// вот сдесь и проблема не могу ответить клиенту !
int hel;
hel = "9999\0";
send (client, hel, strlen(hel), 0);
close(client);

}
}

}


}
else{cout << "NO SERVER" << "\n";}



}

razb
21.06.2009, 14:08
Во первых listen() запускается только один раз, во вторых внимательно пересмотри этот участок кода
char c;
bool finished;
char buffer[1024];
finished = read(client, &c, 10);
cout << client << "---" << c <<"\n";

// вот сдесь и проблема не могу ответить клиенту !
int hel;
hel = "9999\0";
send (client, hel, strlen(hel), 0);
close(client);

Внимательно прочитай документацию по сетевым ф-циям!

--StraNger--
21.06.2009, 14:32
стоит попробовать объявить переменную hel как char

slesh
21.06.2009, 14:39
close -> closesocket
read -> recv
hel - у тя int сделать хотябы char hel[размер]
strlen - тока для строк работает

у тебя наверное при компиле сотни варнингов на экран вылетают

malik555
21.06.2009, 20:52
Вобщем разобрался с отправкой ответа , скрипт немного переделал


int main ( )
{
int sockfd,client;
sockfd = socket(PF_INET, SOCK_STREAM, 0);
socklen_t size;
struct sockaddr_in addr;
bzero(&addr, sizeof(addr));

addr.sin_family = AF_INET;
addr.sin_port = htons(PORT);
addr.sin_addr.s_addr = htonl(INADDR_ANY);

// bind()
if(bind(sockfd,(struct sockaddr *) &addr, sizeof(addr)) != 0){
cout << "Error - bind() !" << "\n";
return 0;
}
// listen()
if(listen(sockfd, 5) != 0){
cout << "Error - listen() !" << "\n";
return 0;
}


while(1) {
size = sizeof(addr);
client = accept(sockfd, (struct sockaddr *) &addr, &size);

if(client > 0){

cout << "Coonect-" <<inet_ntoa(addr.sin_addr) <<"\n";

// - пришли данные
char buffer[1024];
bzero(buffer,sizeof(buffer));
recv(client, buffer, sizeof(buffer),0);
cout << buffer << "\n";

//- ответ клиенту
char *reply = "ggg";
send(client, reply, strlen(reply)+1, 0);

}
}
}



Получается к серверу конектятся клиенты и обмениваются данными - конект поддерживается постоянно с клиентом - и вот проблема как определить на стороне сервера что клиент

отключился - разорвал соеденение ?

malik555
22.06.2009, 22:50
Или подскажите куда капать - по поваду (как определить на стороне сервера что клиент отключился - разорвал соеденение ?)

--StraNger--
22.06.2009, 22:57
Попробуй использовать WSAEventSelect
это события

malik555
23.06.2009, 17:52
Попробуй использовать WSAEventSelect
это события

Да что-то не получается с этим - на perl это все решается очень просто - на c++ еще не найду сдравого решения !

malik555
30.06.2009, 12:10
Вобщем написал сокет сервер - все работает только выдает 2 warning: при компиляции , я не могу их устранить

вот полный код сервера



#include <iostream.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <time.h>
#include <arpa/inet.h>



#define PORT 5190
#define SERVER_IP "000.000.00.000"







void NewClient (int client){


while(1){

char buffer[1024];
bzero(buffer,sizeof(buffer));
if(recv(client, buffer, sizeof(buffer),0) != 0){

cout << buffer "\n";

}

}

}





int main ( )
{
int sockfd,client;
sockfd = socket(PF_INET, SOCK_STREAM, 0);
socklen_t size;
struct sockaddr_in addr;
bzero(&addr, sizeof(addr));

addr.sin_family = AF_INET;
addr.sin_port = htons(PORT);
addr.sin_addr.s_addr = htonl(INADDR_ANY);

// bind()
if(bind(sockfd,(struct sockaddr *) &addr, sizeof(addr)) != 0){
cout << "Error - bind() !" << "\n";
return 0;
}
// listen()
if(listen(sockfd, 5) != 0){
cout << "Error - listen() !" << "\n";
return 0;
}


while(1) {
size = sizeof(addr);
client = accept(sockfd, (struct sockaddr *) &addr, &size);

if(client > 0){

cout << "Coonect-" <<inet_ntoa(addr.sin_addr) <<"\n";

char buffer[1024];
bzero(buffer,sizeof(buffer));
recv(client, buffer, sizeof(buffer),0);
if(buffer == "<policy-file-request/>"){
char *mes = "<?xml version='1.0'?><cross-domain-policy><allow-access-from domain='*' to-ports='*' /></cross-domain-policy>";
send(client, mes, strlen(mes)+1, 0);
close(client);
return 1;
}

if(!fork()){

NewClient(client);

}


}


}



}



а вот предупреждение при компиляции

In file included from /usr/include/c++/4.2/backward/iostream.h:31,
from server.cpp:1:
/usr/include/c++/4.2/backward/backward_warning.h:32:2: warning: #warning This file includes at least one deprecated or antiquated header. Please consider using one of the 32 headers found in section 17.4.1.2 of the C++ standard. Examples include substituting the <X> header for the <X.h> header for C++ includes, or <iostream> instead of the deprecated header <iostream.h>. To disable this warning use -Wno-deprecated.
server.cpp: In function 'int main()':
server.cpp:107: warning: deprecated conversion from string constant to 'char*'

по <iostream.h> пытался так <iostream>
тогда вобще ошибок море все на cout указывают .

а 'char*' тоже незнаю как устранить !

Подскажите пожалуйста !

razb
30.06.2009, 14:29
При использовании <iostream> все обьекты библиотеки находятся в пространстве std, для этого необходимо либо в начале написать using namespace std; либо явно указывать пространство имен, например так std::cout

Далее эту запись замени
char *mes = "<?xml version='1.0'?><cross-domain-policy><allow-access-from domain='*' to-ports='*' /></cross-domain-policy>";
на вот эту
char mes[] = "<?xml version='1.0'?><cross-domain-policy><allow-access-from domain='*' to-ports='*' /></cross-domain-policy>";

П.С. в следующий раз пиши конкретно в какой строке ошибки/предупреждения, а то тут у тебя написано в 107, а кода меньше чем на 100 строк.

malik555
30.06.2009, 15:44
Спасибо !


П.С. в следующий раз пиши конкретно в какой строке ошибки/предупреждения, а то тут у тебя написано в 107, а кода меньше чем на 100 строк.

Это я ступил , я компилил когда полный файл был а на форум выложил - лишнее удалил что-б меньше кода было - оставил главное !

malik555
03.07.2009, 12:35
Собственно возник еще один вопрос по сокетам


весь код вылаживать не буду приведу часть





// когда подключается новый клиент я создаю новый
// процес

if(!fork()){

// и посылаю его в функцию NewClient()
NewClient(client);

}


void NewClient (int client){


while(1){ // бесконечный цыкл


// принимаю сообщение от клиента
char buffer[1024];
bzero(buffer,sizeof(buffer));
recv(client, buffer, sizeof(buffer),0);
if(strlen(buffer) > 0){

cout << buffer ;

}

/* вопрос ! Почему этот цыкл while
выполняется только когда приходит
сообщение от клиента - если нет
сообщений то и цыкл не выполняется
по идеии он должен выполнятся
постоянно ?
*/

}




}

razb
03.07.2009, 13:33
У тебя блокируемые сокеты, это означает что когда выполнение цикла доходит до recv(client, buffer, sizeof(buffer),0); далее ожидается прием данных от клиента, как только они пришли выполнение продолжается.

malik555
03.07.2009, 13:37
У тебя блокируемые сокеты, это означает что когда выполнение цикла доходит до recv(client, buffer, sizeof(buffer),0); далее ожидается прием данных от клиента, как только они пришли выполнение продолжается.


Это вобще правельно так ? и можно сделать что-б цыкл постоянно крутился ?