Форум программистов
 
Контакты: о проблемах с регистрацией, почтой и по другим вопросам пишите сюда - alarforum@yandex.ru, проверяйте папку спам! Обязательно пройдите активизацию e-mail.

Вернуться   Форум программистов > C++ > C/C++ Сетевое программирование
Регистрация

Восстановить пароль
Повторная активизация e-mail


Ответ
 
Опции темы
Старый 18.05.2012, 21:34   #1
Dizelektwo
Пользователь
 
Регистрация: 05.04.2012
Сообщений: 56
По умолчанию Winsock Чат

Здравствуйте, ребята. Я взялся написать простой чат на асинхронных, не блокирующих сокетах и как уже, считаю, стало понятно - столкнулся с небольшой проблемой. Чат написан, для асинхронной работы решил использовать потоки через _beginthreadex, все работает вполне не плохо. Но вот незадача- так как сокеты блокирующие клиент и сервер должны отправлять сообщения только в порядке очереди. А это уж совсем не катит. Вот хочу попросить Вас подсказать мне нормальное решение данной ситуации.
Вот что я набыдлокодил:

Сервер.
PHP код:
#include "stdafx.h"
#include "iostream"
#include "process.h"
#include "winsock2.h"
#include "windows.h"

#pragma comment (lib, "Ws2_32.lib")

using namespace std;



unsigned _stdcall clients(voidsocket) {
    
    
    
char inbuf[30],outBuf[30],toCl[30];
    
unsigned nb;

    
SOCKET p=((SOCKET*)socket)[0];
    
    
int err ioctlsocket(pFIONBIO, (unsigned long *) &nb); 

    
if (
err == SOCKET_ERROR)
{
perror("err convert in nonblock: ");


    

    
recv(p,toCl,sizeof(toCl),0);
    
std::cout << "Client : " << toCl << endl;
    
    while(
1) {
    
    
cin >> outBuf;

    
send(p,outBuf,sizeof(outBuf),0);
    
cout <<"You:_" << outBuf  << endl;
        
    if(!
strcmp(outBuf,"exit")) {
        exit(
1);
    }
    
    
recv(p,inbuf,sizeof(inbuf),0);
    
cout << "Clint: " << inbuf << endl;
    }
    
    return 
0;



int _tmain(int argc_TCHARargv[])
{
    
WSADATA WSAData;

    if(
int err=WSAStartup(0x0202,&WSAData)!=0
        
         { 
perror("WSA err init: "); 
           exit(
1);
         }
    else 
         { 
           
std:: cout << "WSA init _OK" << endl;
         }
    
    
struct sockaddr_in w;
    
SOCKET sock;
     
    
    
char buff[30];
    
int acpt,bnd,list;
    
unsigned int p;

    
    
w.sin_familyAF_INET;
    
w.sin_porthtons(8800);
    
w.sin_addr.s_addr=htonl(INADDR_ANY);
//_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
    
    
sock=socket(AF_INET,SOCK_STREAM,0);
    
    if(
sock==errno
          { 
              
perror("bad sock: ") ; exit(1);
          } 
    else 
          { 
              
std:: cout << "Socket create.." << endl
          }
// _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
    
    
if(bnd=bind(sock,(struct sockaddr*)&w,sizeof(w))==errno
    
               { 
                
std:: cout << "Bind _OK" << endl;
                   } 
    else
               { 
                  
perror("Bind error: "); exit(1);
                  }

//_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

if(list=(listen(sock,30))!=errno
          { 
              
perror("Listen error: ");
            }
    else 
          { 
              
std:: cout << "Listen _OK" << endl;
            }
    
   

    while(
1) {
    
acpt=accept(sock,NULL,NULL); 
    
    
_beginthreadex(NULL,NULL,clients,&acpt,NULL,&p);
    
        
    }
    
closesocket(sock);
    
_endthreadex;
    
system("pause");
    return 
0;

Клиент.

PHP код:
#include "stdafx.h"
#include "iostream"
#include "winsock2.h"
#include "windows.h"

#pragma comment (lib, "Ws2_32.lib")

using namespace std;


int _tmain(int argc_TCHARargv[])
{
    
WSADATA WSAData;

    if(
int err=WSAStartup(0x0202,&WSAData)!=0) {cout <<"error" << endl;}
    else {
cout << "WSA _OK" << endl;}
    

    
struct sockaddr_in w;
    
SOCKET sock;
    
    
char buff[30];
    
    
unsigned int acp,cont;
    
unsigned nb;
    
    
w.sin_familyAF_INET;
    
w.sin_porthtons(8800);
    
w.sin_addr.s_addr=inet_addr("127.0.0.1");

    
sock=socket(AF_INET,SOCK_STREAM,0);
    if(
sock==errno
                   {
                    
perror("sock: ");
                    } 
    else {
         
std:: cout << "sock _OK" << endl;
          }
    
    
int err ioctlsocket(sockFIONBIO, (unsigned long *) &nb); 

    
if (
err == SOCKET_ERROR)
{
perror("err convert in nonblock: ");


    
cont=connect(sock,(struct sockaddr*)&w,sizeof(w)); 
    
    if(
cont==errno)
    {
       
perror("connect error: "); exit(1);
    }
    
 
    
char inBuf[30],outBuf[30];
    
char bb[]="hello server";
    
send(sock,bb,sizeof(bb),0);

    while(
1) {

        
recv(sock,inBuf,sizeof(inBuf),0);
        
cout <<"Server:_ " << inBuf << endl;
        
        
cin >> outBuf;
        
send(sock,outBuf,sizeof(outBuf),0);
        
cout << "You:_ " << outBuf << endl;
        

    }
    
        
closesocket(sock);
    
system("pause");
    return 
0;

В общем хотел организовать полноценный чат, в котором обмен сервер-клиенту и клиент-серверу был бы параллелен, а не очередной.
ioctlsocket должна мне помочь, верно?). Спасибо за раннее.
Запустить два потока- один на чтение, а другой на считывание не вариант?

П.с Последнее попробовал. тоже никуда не годится- половина сообщений приходят с задержкой. А если организовать потоки через мютекс, то это будут те же самые блок сокеты. верно?

Последний раз редактировалось Dizelektwo; 19.05.2012 в 15:29. Причина: добавлено
Dizelektwo вне форума Ответить с цитированием
Старый 19.05.2012, 09:40   #2
Rock-n-Rolla
Форумчанин
 
Регистрация: 11.01.2012
Сообщений: 178
По умолчанию

изучи функции WSARecv, WSASend и прочие WSA___
progromore.i2p - первый русскоязычный портал программистов в скрытосети
Rock-n-Rolla вне форума Ответить с цитированием
Старый 19.05.2012, 14:53   #3
Dizelektwo
Пользователь
 
Регистрация: 05.04.2012
Сообщений: 56
По умолчанию

Спасибо, прочел в msdn про эти ф-ии. Честно говоря понял далеко не все, материала в сети именно по этим средствам win api не так уж и много. Описания в том же msdn говно. Был бы у меня хоть какой-то опыт в сетевой разработке- может вопросов бы и не возникло.
Да и как мне кажется код с этими функциями будет громоздким.
Чем мне не подойдет ioctlsocket с select? Каким образом мне можно перевести сокет в неблокирующий режим в потоке клиента?
Что бы клиент и сервер могли отправлять друг другу пакеты в любом порядке, а не только ты-мне-я-тебе. Есть простые примеры?
Dizelektwo вне форума Ответить с цитированием
Старый 19.05.2012, 19:48   #4
Rock-n-Rolla
Форумчанин
 
Регистрация: 11.01.2012
Сообщений: 178
По умолчанию

Цитата:
Сообщение от Dizelektwo Посмотреть сообщение
Каким образом мне можно перевести сокет в неблокирующий режим в потоке клиента?
при выполнении send проблем быть не должно. а вот при recv программа виснет пока не придут какие либо данные, так вот, чтобы она не висла надо использовать select чтобы узнать есть ли данные на сокете.

Цитата:
Сообщение от Dizelektwo Посмотреть сообщение
Спасибо, прочел в msdn про эти ф-ии. Честно говоря понял далеко не все, материала в сети именно по этим средствам win api не так уж и много. Описания в том же msdn говно.
в MSDN всё прекрасно описано
progromore.i2p - первый русскоязычный портал программистов в скрытосети
Rock-n-Rolla вне форума Ответить с цитированием
Старый 19.05.2012, 20:35   #5
Dizelektwo
Пользователь
 
Регистрация: 05.04.2012
Сообщений: 56
По умолчанию

Ну на счет msdn не соглашусь, на счет общей справки- пойдет, как учебный материал- довольно посредственно и уныло. Убогие xemplы неудобного для восприятия размера. Понятие "будь проще" тому ресурсу бы подошло как нельзя к стати. Для изучения нужен минимализированный исходник , а там начинающему плюсовику еще нужно отдирать ненужных мух(левых функций) прежде чем понять алгоритм необходимой функции. Само описание- да, не плохое. Изредка попадаются нормальные исходники. В целом - учиться по msdn это садомазохизм от мелкомягких. Справочник, правда, что надо.

Цитата:
, чтобы она не висла надо использовать select чтобы узнать есть ли данные на сокете.
Благодарю, об этом я вкурсе. Теории полно, а исходников вот уж совсем мало по моему вопросу.
Уже как день не могу найти ничего внятного.

П.с смотрю примера полноценного так и нет. Ну да ладно, тогда уж методом тыка.
К стати, толкового исходника для ф-ий ioctlsocket и select в msdn нет. Для последней его нет и в помине. Одно лишь описание.
Ну да ладно, спасибо тебе все же за не безразличие и кой какие подсказки. Все равно ведь я его до ума довиду рано или чуть позже)

Последний раз редактировалось Dizelektwo; 19.05.2012 в 21:09.
Dizelektwo вне форума Ответить с цитированием
Старый 20.05.2012, 08:59   #6
Rock-n-Rolla
Форумчанин
 
Регистрация: 11.01.2012
Сообщений: 178
По умолчанию

Цитата:
Сообщение от Dizelektwo Посмотреть сообщение
Ну на счет msdn не соглашусь, на счет общей справки- пойдет, как учебный материал- довольно посредственно и уныло. Убогие xemplы неудобного для восприятия размера. Понятие "будь проще" тому ресурсу бы подошло как нельзя к стати. Для изучения нужен минимализированный исходник , а там начинающему плюсовику еще нужно отдирать ненужных мух(левых функций) прежде чем понять алгоритм необходимой функции. Само описание- да, не плохое. Изредка попадаются нормальные исходники. В целом - учиться по msdn это садомазохизм от мелкомягких.
Я когда-то хотел запилить статью по работе с WSA-функциями с примерами их пременения и подробными описаниями на примере SOCKS5 на своём вики-проекте, но как всегда всё упёрлось в нехватку времени
progromore.i2p - первый русскоязычный портал программистов в скрытосети
Rock-n-Rolla вне форума Ответить с цитированием
Ответ

Здесь нужно купить рекламу за 20 тыс руб в месяц! ) пишите сюда - alarforum@yandex.ru
Без учёта ботов - 20000 человек в день, 350000 в месяц.

Опции темы


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Многопоточный чат на winsock btf Visual C++ 15 28.12.2012 06:15
Winsock Чат Dizelektwo C/C++ Сетевое программирование 0 18.05.2012 21:24
Чат через winsock Jasper92 Помощь студентам 0 23.11.2010 15:48
WinSock Onekey Обсуждение статей 0 20.08.2010 12:04
WinSock ImmortalAlexSan Работа с сетью в Delphi 1 11.05.2010 14:42