Кодим сокеты на MFC
cuttah (cutter@real.xakep.ru)
Xakep, номер #061, стр. 061-090-3
CServerSocket::CServerSocket(CxoDlg* pDlg)
{
m_pDlg = pDlg;
}
Все. Этой строкой мы связали наш серверный сокет с диалоговым окном. Осталось только добавить событие для входящих соединений. Для этого пропиши в метод OnAccept такой вот код:
void CServerSocket::OnAccept(int nErrorCode)
{
// TODO: Add your specialized code here and/or call the base class
CSocket::OnAccept(nErrorCode);
m_pDlg->NewConnect();
}
Теперь при новом соединении вызовется метод OnAccept. В нем произойдет согласие на входящий коннект, после чего при помощи m_pDlg->NewConnect(); управление передастся диалоговому окну.
После создания серверного сокета перейдем к реализации клиентской части. Для начала создавай новый класс CClientSocket на основе того же CSocket. В хедерниках нового класса добавь объявление класса СxoDlg. Далее измени конструктор класса. Поменяй пустой CClientSocket(); на CClientSocket(CxoDlg* pDlg);. А в .cpp файле пропиши следующие строки:
CClientSocket::CClientSocket(CxoDlg* pDlg)
{
m_pDlg = pDlg;
}
Здесь, как и в случае с CServerSocket, при создании нового объекта будет передаваться ссылка на диалоговое окно (в моем случае это класс CxoDlg).
Передача данных
Наше приложение может выступать как в роли сервера, так и в роли клиента. Серверная часть запускается по нажатию клавиши Create server. После ее клика выполняется событие OnBnClickedCreate, где создается серверный сокет. Вот как выглядит этот код:
void CxoDlg::OnBnClickedCreate()
{
// TODO: Add your control notification handler code here
m_pSocket = new CServerSocket(this);
m_pSocket->Create(m_port);
m_pSocket->Listen();
}
В m_port, как нетрудно догадаться, хранится значение порта. По умолчанию это порт 2345. Само значение m_port прописано как константа. Так что, если ты захочешь сделать этот параметр динамичным, то добавь на форме еще одно поле Edit и свяжи его с этой переменной (только не забудь убрать с нее статус константы).
Далее, если произойдет соединение, то вызовется метод NewConnect, в котором прописаны некоторые начальные данные для новой партии в крестики-нолики:
void CxoDlg::NewConnect(void)
{
pSocket = new CClientSocket(this);
m_pSocket->Accept(*pSocket);
m_type = 1;
m_turn = 1;
m_connected = 1;
}
В переменной m_type прописывается тип игрока. Т.е. чем он будет играть – крестиками или ноликами. Один обозначает, что это крестик, двойка – нолик. В m_turn отображается состояние хода. Если это 1, то ход твой, 0 – противника. Соответственно, с каждым ходом это значение будет заменяться противоположным.
Теперь о запуске клиентской части. При нажатии батона Connect запускается метод OnBnClickedButtonConnect. В нем происходит обновление данных в форме при помощи UpdateData (true);. Далее объявляется динамический объект pSocket класса CClientSocket, после чего происходит соединение. Если все прошло успешно, т.е. соединение установлено, то в переменные m_type и m_turn помещаются следующие значения:
if (pSocket->Connect(m_sAdr, m_port))
{
m_type=2;
m_turn=0;
m_connected=1;