Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Сети > Сервер: wincosk stream synchr


Автор: Flash_ 20.12.2006, 22:08
Всем привет.

Есть синхронный потоковый сервак на с++, код создания ниже.
Суть в том что, все кроме той-же технологии клиента не могут подключиться к серверу 
(err# 10061 или 10060)

я пробовал и php и ActionScript и telnet'ом...

Есть мнение что 'синхронность' не входит в понятие сокетов berkley, и поэтому и происходит то что происходит!?

Кто чё думает по этому поводу?
Код

int server::create(USHORT p)
{
    if(connected)
        return 1;
    char ip[13];
    strcpy(ip,"127.0.0.1");

    int res=0;
    WSADATA data;
    port=p;     
    if(!WSAStartup(MAKEWORD(2,0),&data))
    {
        sock=socket(AF_INET,SOCK_STREAM,0);
        if(sock!=INVALID_SOCKET)
        {           
            in_addr ia;
            
            ia.S_un.S_addr=INADDR_ANY;
            sockaddr *p;            
            sockaddr_in x={
                            AF_INET,
                            port,
                            ia,              
                          };
                p=(sockaddr*)&x;            
                if(!bind(sock,p,sizeof(*p)))
                {
                    if(!listen(sock,    1))
                    {                           
                            DWORD id;
                            ct_handle=CreateThread(0,   0,  connect_thread,this,0,&id); 
                                 //поток с acept'ом

                    }else                   
                       res=WSAGetLastError();   
            }else           
                res=WSAGetLastError();  
        }
        else
            res=WSAGetLastError();      
    }else   
        res=WSAGetLastError();  

    connected=!(bool)res;
    return res;
}

Автор: witex 21.12.2006, 02:21
Первый коментарий на счёт ветвелний if  не надо усложнять просто если ошибка сразу делаешь return;
Дальше! Зачем такие преоброзования со структурой которую ты передаёшь bind?
темболее у тебя есть параметр функции p,  а ты его ещё под структуру объявляешь! Я понимаю кнечно что ты через указатель ему структуру передаёшь но не так уж и удобно.
я думаю так удобнее будет! это раз!
Код

         
            sockaddr_in x={
                            AF_INET,
                            port,
                            0,              
                          };
                 
 if(!bind(sock,(sockkaddr *)&x,sizeof(x)))

далее приведи ко accept потому что может быть там загвоздка, а не в части создания прикрипления сервера к порту.
я думаю ты знаешь что для accept нужен хендл сокета сервера! у тебя создаёться поток. но что то не вижу что ты передаёшь туда сокет, или он у тебя глобальный? Ну не суть покажи код акцепта.И всё таки я остаюсь при своём мнении что конечно красиво указателю придавать разные типы.. но суть в том что зачем две струтуры объявлять если можно обойтий одной! одну чисто для адресного ip пространства что принимает все конекты, а вторая для остальных.. покажи код accept, и лудше бинд сделай как я написал!

Автор: ptr 21.12.2006, 12:01
Flash_, приведи весь код.

Автор: Flash_ 21.12.2006, 21:38
Во первых smile
Спасибо witex за толковые замечания. 

Во вторых
Цитата(witex @  21.12.2006,  02:21 Найти цитируемый пост)
Первый коментарий на счёт ветвелний if  не надо усложнять просто если ошибка сразу делаешь return;


так красивей smile 

Цитата(witex @  21.12.2006,  02:21 Найти цитируемый пост)
Дальше! Зачем такие преоброзования со структурой которую ты передаёшь bind?темболее у тебя есть параметр функции p,  а ты его ещё под структуру объявляешь! Я понимаю кнечно что ты через указатель ему структуру передаёшь но не так уж и удобно.я думаю так удобнее будет! это раз!


Спасибо за замечание  подумаю. НО

А как по твоему я укажу INADDR_ANY? или в твоём варианте указание адресса сервера не нужно?



Цитата(witex @  21.12.2006,  02:21 Найти цитируемый пост)
далее приведи ко accept потому что может быть там загвоздка, а не в части создания прикрипления сервера к порту.

вот статический метод класса для потока.
самое интересное (под отладчиком проверял)что при коннекте telnetom или php stream_socket поток не выходит из accepta!
Код

DWORD server::connect_thread(void *param)
{
    server *srv=(server*)param;
    SOCKET ns=INVALID_SOCKET ;
    sockaddr_in sa;    
    int i=sizeof(sa);    
    int cnt=0;           
         DWORD id;
    
    while((ns=accept(srv->sock,(sockaddr*)&sa,&i))!=INVALID_SOCKET &&srv->clients.size()<100)
    {        
        sclient *tmp=new sclient();        
                  //sclient - клиент в серверном представлении, там новый сокет, хендл приёмо-отправочного потока и ещё всякая фигня
        strcpy(tmp->ip,inet_ntoa(sa.sin_addr)?inet_ntoa(sa.sin_addr):"none");
                  //заполняем новый объект
        tmp->s=ns; 
        tmp->server=srv;
        srv->clients.push_back(tmp);        
                  //доб его в вектор всех клиентов

        cout<<"connect size="<<srv->clients.size()<<"\n";
        cout<<"connect ip="<<tmp->ip<<"\n";
                  //запускаем его поток
        tmp->th=CreateThread(0,    0,recv_thread,tmp,0,&id);    
        cnt++;        
    }    
    return WSAGetLastError();
}



Цитата(witex @  21.12.2006,  02:21 Найти цитируемый пост)
я думаю ты знаешь что для accept нужен хендл сокета сервера! у тебя создаёться поток. но что то не вижу что ты передаёшь туда сокет, или он у тебя глобальный? 


Я привёл код метода класса, сокет sock - переменная этого класса соответствено.
Я в поток передаю this класса. из зиса там и беру.

Цитата(witex @  21.12.2006,  02:21 Найти цитируемый пост)
И всё таки я остаюсь при своём мнении что конечно красиво указателю придавать разные типы.. но суть в том что зачем две струтуры объявлять если можно обойтий одной!


Согласен.

Цитата(witex @  21.12.2006,  02:21 Найти цитируемый пост)
 и лудше бинд сделай как я написал!

не вопрос

Приёмо отправочный поток я думую вам не нужен. так как он даже не вызывается.

Автор: Flash_ 21.12.2006, 22:16
и еще имеется в виду то что, сервер не вообще не работает, а не работает с другими клиентами, отличными от мной написанного.

Автор: witex 21.12.2006, 23:18
Код

sockaddr_in x={
                            AF_INET,
                            port,
                            0    //он и выдёт так    INADDR_ANY Это числовая константа, для сведения     
                          };


 смысл?
Цитата

 SOCKET ns=INVALID_SOCKET ;

а остальное позже посмотрю!

Автор: Flash_ 21.12.2006, 23:35
Цитата(witex @  21.12.2006,  23:18 Найти цитируемый пост)
 смысл?Цитата SOCKET ns=INVALID_SOCKET ;

для отчётности smile

А ты подключался к своиму серверу из других платформ (telnet, php...)?

Добавлено @ 23:39 
Цитата(witex @  21.12.2006,  23:18 Найти цитируемый пост)
код C++1:2:3:4:5:sockaddr_in x={                            AF_INET,                            port,                            0    //он и выдёт так    INADDR_ANY Это числовая константа, для сведения      


блина...
я забыл посмотреть чему константа равна и чтё её ожно задать в sock_addr_in...
ты прав такая махинация со структурами практически не имеет смысла...

Автор: witex 22.12.2006, 01:59
слушай, к своему серверу telnet подключал как нефиг. так что вот!
Слушай дай полный исходник! мож даже файл проекта прислать! Может где в другом месте ошибка!
Так что вот! Мож продебагю найду ошибку.

Автор: Flash_ 22.12.2006, 16:49
Это...
Я тебе в pm выслал сырс...

Автор: Flash_ 22.12.2006, 21:18
witex, а может дело в том что, я собираю 2003-ей студией? может проблема в реализации на ms?


Автор: Flash_ 27.12.2006, 21:56
...
спасибо witex, за решение пробдемы.

Код

  sockaddr_in x={
                            AF_INET,
                            htons(port),// вот здесь собака была зарыта!
                            ia,              
                          };
 



из статьи Криса Касперски (кому интересно)

Цитата

Сетевой порядок байт

Среди производителей процессоров нет единого мнения на счет порядка следования младших и старших байт. Так например, у микропроцессоров Intel младшие байты располагаются по меньшим адресам, а у микропроцессоров Motorola 68000 - наоборот. Естественно, это вызывает проблемы при межсетевом взаимодействии, поэтому, был введен специальный сетевой порядок байт, предписывающий старший байт передавать первым (все не так, как у Intel). 

Для преобразований чисел из сетевого формата в формат локального хоста и наоборот предусмотрено четыре функции - первые две манипулируют короткими целыми (16-битными словами), а две последние - длинными (32-битными двойными словами): u_short ntohs (u_short netshort); u_short htons (u_short hostshort ); u_long ntohl (u_long netlong ); u_long htonl (u_long hostlong); 






Автор: witex 27.12.2006, 22:15
Пометь тогда как решённая, тему!;)

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)