Как применить accept?
От: -SS-  
Дата: 13.11.04 14:50
Оценка:
вообщем создаю сокет
WSADATA WsaData;
SOCKET s;
SOCKET s1;
CSocket sa;
SOCKADDR_IN sin;
BOOL CMyDialog::OnInitDialog()
{
CDialog::OnInitDialog();
int err = WSAStartup (0x0101, &WsaData);
if (err == SOCKET_ERROR)
{
AfxMessageBox("error socket");
return 1;
}
s = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
sin.sin_family = AF_INET;
sin.sin_port = htons(8423);
sin.sin_addr.s_addr = INADDR_ANY;
err = bind( s, (LPSOCKADDR)&sin, sizeof(sin) );
err = listen( s, SOMAXCONN);

}
Делаю кнопку на диалоге
void CMyDialog::OnBUTTON7()
{
sa.Create();
if (sa.Connect("192.168.10.1",8423))
{
AfxMessageBox("Ok connect ");
}
else
AfxMessageBox("Error Connect");
CString buffer = " Hello World";
sa.Send(buffer, 500, 0);
sa.Close();

}
Когда нажимаю на кнопку, то как и надо появляется сообщение OK connect,
а вот как принять сообщение от sa.Send? Т.е. моя прога как бы себе посылает сообщение,
знаю что нужно использовать accept и recieve, но вот не знаю как это использовать .
Необходима что бы она себе передала Hello World и вывела AfxMessageBox Hello World.
Помогите пожалуйста.
Re: Как применить accept?
От: sa83  
Дата: 13.11.04 15:52
Оценка:
Здравствуйте, -SS-, Вы писали:

SS>вообщем создаю сокет

SS>WSADATA WsaData;
SS>SOCKET s;
SS>SOCKET s1;
SS>CSocket sa;
SS>SOCKADDR_IN sin;
SS>BOOL CMyDialog::OnInitDialog()
SS>{
SS> CDialog::OnInitDialog();
SS> int err = WSAStartup (0x0101, &WsaData);
SS> if (err == SOCKET_ERROR)
SS> {
SS> AfxMessageBox("error socket");
SS> return 1;
SS> }
SS> s = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
SS> sin.sin_family = AF_INET;
SS> sin.sin_port = htons(8423);
SS> sin.sin_addr.s_addr = INADDR_ANY;
SS> err = bind( s, (LPSOCKADDR)&sin, sizeof(sin) );
SS> err = listen( s, SOMAXCONN);

SS>}

SS>Делаю кнопку на диалоге
SS>void CMyDialog::OnBUTTON7()
SS>{
SS> sa.Create();
SS> if (sa.Connect("192.168.10.1",8423))
SS> {
SS> AfxMessageBox("Ok connect ");
SS> }
SS> else
SS> AfxMessageBox("Error Connect");
SS> CString buffer = " Hello World";
SS> sa.Send(buffer, 500, 0);
SS> sa.Close();

SS>}

SS>Когда нажимаю на кнопку, то как и надо появляется сообщение OK connect,
SS>а вот как принять сообщение от sa.Send? Т.е. моя прога как бы себе посылает сообщение,
SS>знаю что нужно использовать accept и recieve, но вот не знаю как это использовать .
SS>Необходима что бы она себе передала Hello World и вывела AfxMessageBox Hello World.
SS>Помогите пожалуйста.

Может, использование потоков поможет?
К примеру:
WSADATA WsaData;
SOCKET s;
SOCKET s1;
CSocket sa;
SOCKADDR_IN sin;
char receiveBuffer[300];
BOOL CMyDialog::OnInitDialog()
{
    CDialog::OnInitDialog();
    int err = WSAStartup (0x0101, &WsaData);
    if (err == SOCKET_ERROR)
    {
           AfxMessageBox("error socket");
           return 1;
    }
    s = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
    sin.sin_family = AF_INET;
    sin.sin_port = htons(8423);
    sin.sin_addr.s_addr = INADDR_ANY;
    err = bind( s, (LPSOCKADDR)&sin, sizeof(sin) );
    err = listen( s, SOMAXCONN);
     AfxBeginThread(receiveThread,&s);
}
 
void CMyDialog::OnBUTTON7()
{
    sa.Create();
        if (sa.Connect("192.168.10.1",8423))
    {
        AfxMessageBox("Ok connect ");
    } 
    else
        AfxMessageBox("Error Connect");
    CString buffer = " Hello World";
        sa.Send(buffer, 500, 0);
    sa.Close(); 
}
UINT receiveThread(LPVOID lParam){
     SOCKET& sock = (SOCKET*)lParam;
     SOCKET socket;
     sockaddr_in sockAddr;
     int lenSockAddr=sizeof(sockAddr);
     if(socket=accept(&sock,(LPSOCKADDR)&sockAddr,&lenSockAddr))!=INVALID_SOCKET) 
     {
          recv(socket,receiveBuffer,sizeof(receiveBuffer),0);
          AfxMessageBox(...);
     }
}
Re[2]: Как применить accept?
От: sa83  
Дата: 13.11.04 15:55
Оценка:
Пардон, опечатка:
if(socket=accept(*sock,(LPSOCKADDR)&sockAddr,&lenSockAddr))!=INVALID_SOCKET)
Re[2]: Как применить accept?
От: -SS-  
Дата: 14.11.04 11:56
Оценка:
Здравствуйте, sa83, Вы писали:
S>Может, использование потоков поможет?
S>К примеру:
S>
S>WSADATA WsaData;
S>SOCKET s;
S>SOCKET s1;
S>CSocket sa;
S>SOCKADDR_IN sin;
S>char receiveBuffer[300];
S>BOOL CMyDialog::OnInitDialog()
S>{
S>    CDialog::OnInitDialog();
S>    int err = WSAStartup (0x0101, &WsaData);
S>    if (err == SOCKET_ERROR)
S>    {
S>           AfxMessageBox("error socket");
S>           return 1;
S>    }
S>    s = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
S>    sin.sin_family = AF_INET;
S>    sin.sin_port = htons(8423);
S>    sin.sin_addr.s_addr = INADDR_ANY;
S>    err = bind( s, (LPSOCKADDR)&sin, sizeof(sin) );
S>    err = listen( s, SOMAXCONN);
S>     AfxBeginThread(receiveThread,&s);
S>}
 
S>void CMyDialog::OnBUTTON7()
S>{
S>    sa.Create();
S>        if (sa.Connect("192.168.10.1",8423))
S>    {
S>        AfxMessageBox("Ok connect ");
S>    } 
S>    else
S>        AfxMessageBox("Error Connect");
S>    CString buffer = " Hello World";
S>        sa.Send(buffer, 500, 0);
S>    sa.Close(); 
S>}
S>UINT receiveThread(LPVOID lParam){
S>     SOCKET& sock = (SOCKET*)lParam;
S>     SOCKET socket;
S>     sockaddr_in sockAddr;
S>     int lenSockAddr=sizeof(sockAddr);
S>     if(socket=accept(&sock,(LPSOCKADDR)&sockAddr,&lenSockAddr))!=INVALID_SOCKET) 
S>     {
S>          recv(socket,receiveBuffer,sizeof(receiveBuffer),0);
S>          AfxMessageBox(...);
S>     }
S>}
S>

извините, а можно без потоков(если можно), а то я только начинаю и приведённый выше код не догнал и не заработал он , как нибудь попроще и понаглядней можно?
Re[3]: Как применить accept?
От: sa83  
Дата: 14.11.04 16:19
Оценка:
Я проверил вот этот код, у меня заработало.Он несколько отличается от предыдущего, но все еще использует отдельный поток для установления соединения и получения данных. Почему я предложил отдельный поток? Дело в том, что когда просто создаешь сокет, он по умолчанию блокирующий, и если вызвать функцию accept() в главном потоке, она просто напросто заблокирует его, и обработчик нажатия на кнопку никогда не вызовется (если я не ошибаюсь, если ошибаюсь, то напишите кто-нибудь, дабы развеять мое заблуждение, сам не проверял). Можно, конечно, создать неблокирующий сокет. Но как это поможет в данном случае, сразу не соображу.
WSADATA WsaData;
SOCKET s;
CSocket sa;
SOCKADDR_IN sin;
char receiveBuffer[300];
BOOL CMyDialog::OnInitDialog()
{
    CDialog::OnInitDialog();
    int err = WSAStartup (0x0101, &WsaData);
    if (err == SOCKET_ERROR)
    {
           AfxMessageBox("error socket");
           return 1;
    }
    s = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
    sin.sin_family = AF_INET;
    sin.sin_port = htons(8423);
    sin.sin_addr.s_addr = INADDR_ANY;
    err = bind( s, (LPSOCKADDR)&sin, sizeof(sin) );
    err = listen( s, SOMAXCONN);
     AfxBeginThread(receiveThread,NULL);
}
 
void CMyDialog::OnBUTTON7()
{
    sa.Create();
        if (sa.Connect("192.168.10.1",8423))
    {
        AfxMessageBox("Ok connect ");
    } 
    else
        AfxMessageBox("Error Connect");
    CString buffer = " Hello World";
        sa.Send(buffer, 500, 0);
    sa.Close(); 
}
UINT receiveThread(LPVOID lParam){
     SOCKET socket;
     sockaddr_in sockAddr;
     int lenSockAddr=sizeof(sockAddr);
     if(socket=accept(s,(LPSOCKADDR)&sockAddr,&lenSockAddr))!=INVALID_SOCKET) 
     {
          recv(socket,receiveBuffer,sizeof(receiveBuffer),0);
          CString str;
        str.Format("%s",receiveBuffer);
        AfxMessageBox(str);          
     }
     return 1;
}
Re[4]: Как применить accept?
От: -SS-  
Дата: 14.11.04 23:47
Оценка:
Здравствуйте, sa83, Вы писали:

S>Я проверил вот этот код, у меня заработало.Он несколько отличается от предыдущего, но все еще использует отдельный поток для установления соединения и получения данных. Почему я предложил отдельный поток? Дело в том, что когда просто создаешь сокет, он по умолчанию блокирующий, и если вызвать функцию accept() в главном потоке, она просто напросто заблокирует его, и обработчик нажатия на кнопку никогда не вызовется (если я не ошибаюсь, если ошибаюсь, то напишите кто-нибудь, дабы развеять мое заблуждение, сам не проверял). Можно, конечно, создать неблокирующий сокет. Но как это поможет в данном случае, сразу не соображу.

S>
S>WSADATA WsaData;
S>SOCKET s;
S>CSocket sa;
S>SOCKADDR_IN sin;
... 
S>          CString str;
S>        str.Format("%s",receiveBuffer);
S>        AfxMessageBox(str);          
S>     }
S>     return 1;
S>}
S>

Спасибо, помогло, но вот только сообщение можно отправить всего одни раз, т.е. при повторном нажатии на кнопу больше ни чего не происходит, как это побороть?
Re[5]: Как применить accept?
От: sa83  
Дата: 15.11.04 06:44
Оценка:
Здравствуйте, -SS-, Вы писали:

SS>Здравствуйте, sa83, Вы писали:


S>>Я проверил вот этот код, у меня заработало.Он несколько отличается от предыдущего, но все еще использует отдельный поток для установления соединения и получения данных. Почему я предложил отдельный поток? Дело в том, что когда просто создаешь сокет, он по умолчанию блокирующий, и если вызвать функцию accept() в главном потоке, она просто напросто заблокирует его, и обработчик нажатия на кнопку никогда не вызовется (если я не ошибаюсь, если ошибаюсь, то напишите кто-нибудь, дабы развеять мое заблуждение, сам не проверял). Можно, конечно, создать неблокирующий сокет. Но как это поможет в данном случае, сразу не соображу.

S>>
S>>WSADATA WsaData;
S>>SOCKET s;
S>>CSocket sa;
S>>SOCKADDR_IN sin;
SS>... 
S>>          CString str;
S>>        str.Format("%s",receiveBuffer);
S>>        AfxMessageBox(str);          
S>>     }
S>>     return 1;
S>>}
S>>

SS>Спасибо, помогло, но вот только сообщение можно отправить всего одни раз, т.е. при повторном нажатии на кнопу больше ни чего не происходит, как это побороть?
"Загони" recv() в бесконечный цикл, но надо в таком случае правильно закончить поток, а то он будет висеть
Re[6]: Как применить accept?
От: -SS-  
Дата: 16.11.04 00:56
Оценка:
Здравствуйте, sa83, Вы писали:

S>Здравствуйте, -SS-, Вы писали:


SS>>Здравствуйте, sa83, Вы писали:


S>>>Я проверил вот этот код, у меня заработало.Он несколько отличается от предыдущего, но все еще использует отдельный поток для установления соединения и получения данных. Почему я предложил отдельный поток? Дело в том, что когда просто создаешь сокет, он по умолчанию блокирующий, и если вызвать функцию accept() в главном потоке, она просто напросто заблокирует его, и обработчик нажатия на кнопку никогда не вызовется (если я не ошибаюсь, если ошибаюсь, то напишите кто-нибудь, дабы развеять мое заблуждение, сам не проверял). Можно, конечно, создать неблокирующий сокет. Но как это поможет в данном случае, сразу не соображу.

S>>>
S>>>WSADATA WsaData;
S>>>SOCKET s;
S>>>CSocket sa;
S>>>SOCKADDR_IN sin;
SS>>... 
S>>>          CString str;
S>>>        str.Format("%s",receiveBuffer);
S>>>        AfxMessageBox(str);          
S>>>     }
S>>>     return 1;
S>>>}
S>>>

SS>>Спасибо, помогло, но вот только сообщение можно отправить всего одни раз, т.е. при повторном нажатии на кнопу больше ни чего не происходит, как это побороть?
S>"Загони" recv() в бесконечный цикл, но надо в таком случае правильно закончить поток, а то он будет висеть
Т.е. как правильно закончить поток? Я вот сделал так:

UINT receiveThread(LPVOID lParam){
     SOCKET socket;
     sockaddr_in sockAddr;
     int lenSockAddr=sizeof(sockAddr);
     while (TRUE) { // это добавил
     if((socket=accept(s,(LPSOCKADDR)&sockAddr,&lenSockAddr))!=INVALID_SOCKET) 
     {
         recv(socket,receiveBuffer,sizeof(receiveBuffer),0);
                 CString str;
                 str.Format("%s",receiveBuffer);
         AfxMessageBox(str); 
         //m_edit1.SetWindowText(str);  // это не работает
     }
     } // и это добавил
      return 1;
}


вроде (3*тьфу) работает
Уменя ещё один вопросик
Вообщем у меня на диалоге 2 EditBox m_edit и m_edit1. Из m_edit берётся текст и посылается
, после того как его примет поток мне нужно вывести принятый текст в m_edit1. Добавил это
m_edit1.SetWindowText(str); — всё без проблем откомпилелось, запускаю, посылаю текст, текст приходит и сразу прям ошибка(на том шаге когда в editbox текст выводить надо было) с тремя вариантами ответа Прервать Повтор Пропустить. Помогите плиз и с этой задачкой .
Re[7]: Как применить accept?
От: sa83  
Дата: 16.11.04 11:20
Оценка:
SS>Вообщем у меня на диалоге 2 EditBox m_edit и m_edit1. Из m_edit берётся текст и посылается
SS>, после того как его примет поток мне нужно вывести принятый текст в m_edit1. Добавил это
SS>m_edit1.SetWindowText(str); — всё без проблем откомпилелось, запускаю, посылаю текст, текст приходит и сразу прям ошибка(на том шаге когда в editbox текст выводить надо было) с тремя вариантами ответа Прервать Повтор Пропустить. Помогите плиз и с этой задачкой .

Ну в общем, понятно. Потоковая функция у тебя верно глобальная или статическая функция-член, в которой ты не имеешь права обращаться к полям твоего класса. Предлагаю сделать так:
BOOL CMyDialog::OnInitDialog()
{
    CDialog::OnInitDialog();
    int err = WSAStartup (0x0101, &WsaData);
    if (err == SOCKET_ERROR)
    {
           AfxMessageBox("error socket");
           return 1;
    }
    s = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
    sin.sin_family = AF_INET;
    sin.sin_port = htons(8423);
    sin.sin_addr.s_addr = INADDR_ANY;
    err = bind( s, (LPSOCKADDR)&sin, sizeof(sin) );
    err = listen( s, SOMAXCONN);
    AfxBeginThread(receiveThread,this);
}
 
void CMyDialog::OnBUTTON7()
{
    sa.Create();
        if (sa.Connect("192.168.10.1",8423))
    {
        AfxMessageBox("Ok connect ");
    } 
    else
        AfxMessageBox("Error Connect");
    CString buffer = " Hello World";
        sa.Send(buffer, 500, 0);
    sa.Close(); 
}
UINT receiveThread(LPVOID lParam){
     CMyDialog* myDlg=(CMyDialog*)lParam;
     
     SOCKET socket;
     sockaddr_in sockAddr;
     int lenSockAddr=sizeof(sockAddr);
     if(socket=accept(s,(LPSOCKADDR)&sockAddr,&lenSockAddr))!=INVALID_SOCKET) 
     {
          recv(socket,receiveBuffer,sizeof(receiveBuffer),0);
          CString str;
        str.Format("%s",receiveBuffer);
        myDlg->m_edit1.SetWindowText(str);          
     }
     return 1;
}
Re: Как применить accept?
От: butcher Россия http://bu7cher.blogspot.com
Дата: 16.11.04 11:33
Оценка:
Здравствуйте, -SS-, Вы писали:

SS>Когда нажимаю на кнопку, то как и надо появляется сообщение OK connect,

SS>а вот как принять сообщение от sa.Send? Т.е. моя прога как бы себе посылает сообщение,
SS>знаю что нужно использовать accept и recieve, но вот не знаю как это использовать .
SS>Необходима что бы она себе передала Hello World и вывела AfxMessageBox Hello World.

В вашем случае возможно было бы удобнее использовать асинхронные сокеты. см. MSDN: WSAAsyncSelect.
Удобнее, в плане того, что есть окна, которые могут получать сообщения.

Нет ничего невозможного..
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.