wxWidgets sockets编程学习

wxWidgets sockets编程学习
工作环境:CodeBlock17.12,wxWidgets3.0.4,win10,GNU编译器
目的:学习wxWidgets下使用wxSocket进行sockets编程,实现UDP, TCP, HTTP(URL)的功能。包括服务器端和客户端的代码演示。
源代码地址:https://download.csdn.net/download/qq_23313467/12129468
一.建立工程过程
Step1:CodeBlock中 File/New/Project… , 然后选择wxWidgets Project,点击“Go”按钮。如下图:
Step2:不选择“Skip this page next time”,点击“Next>”按钮;
Step3:选择“wxWidgets 3.0.x”选项(本project是wxWidget3.0.4),点击“Next>”按钮;
Step4:在Project tiltl输入“SocketServer”,点击“Next>”按钮;
Step5:Author内容,可以随便输入,点击“Next>”按钮;
Step6:Prefered GUI Builder,选择“wxSmith”;Application Type,选择“Frame Based”点击“Next>”按钮;
Step7:wxWidgets’ location: 输入“d:\wxWidgets-3.0.4” (根据实际情况输入wxWidgets的安装目录),点击“Next>”按钮;
Step8:在Complier、Debug、Release选择,使用默认的选项),点击“Next>”按钮;
Step9:在wxWigets Library settings,只选中“use wxWidgets DLL”和“Enable unicode”,其他不选,点击“Next>”按钮;
Step10:选择“wxNet”选项(好像没什么用),点击“Finish”按钮;
Step11:在Projet/ Build Options…中 Debug/Linker settings 的Link libraries中Add 文件libwxbase30ud_net.a , Release/Linker settings 的Link libraries中Add 文件libwxbase30u_net.a 。
二.Project 代码修改
下面是UDP、TCP、http(URL)主要代码介绍。详细可以下载演示工程的完整代码。SocketsCleint包括了UDP、TCP、http(URL)客户端操作。SocketsServer包括了UDP、TCP服务器端操作。
1.UDP的主要代码
(1)UDP客户端主要代码
wxIPV4address addrLocal;
addrLocal.Hostname();
wxDatagramSocket sock(addrLocal);
wxIPV4address addrPeer;
addrPeer.Hostname(hostname);
addrPeer.Service(3000);
wxLogMessage(“Testing UDP with peer at %s:%u”,
addrPeer.IPAddress(), addrPeer.Service());

char buf[] = "Uryyb sebz pyvrag!";
if ( sock.SendTo(addrPeer, buf, sizeof(buf)).LastCount() != sizeof(buf) )
{
    wxLogMessage("ERROR: failed to send data");
    return;
}

if ( sock.RecvFrom(addrPeer, buf, sizeof(buf)).LastCount() != sizeof(buf) )
{
    wxLogMessage("ERROR: failed to receive data");
    return;

}
使用SendTo()发送UDP数据,使用RecvFrom()接收UDP数据。
(2)UDP服务器端主要代码
IPaddress addr;
addr.Service(3000);
wxDatagramSocket sock(addr);

char buf[1024];
size_t n = sock.RecvFrom(addr, buf, sizeof(buf)).LastCount();
if ( !n )
{
    wxLogMessage("ERROR: failed to receive data");
    return;
}

wxLogMessage("Received \"%s\" from %s:%u.",
             wxString::From8BitData(buf, n),
             addr.IPAddress(), addr.Service());


if ( sock.SendTo(addr, buf, n).LastCount() != n )
{
    wxLogMessage("ERROR: failed to send data");
    return;
}

服务器端的代码和客户端几乎是相同的,只是先RecvFrom()接收将接收到的数据SendTo()发送回去。
(3)TCP客户端主要代码
// 第一步:创建socket
m_sock = new wxSocketClient();

// 设置事件响应消息
m_sock->SetEventHandler(*this, SOCKET_ID);
m_sock->SetNotify(wxSOCKET_CONNECTION_FLAG |
wxSOCKET_INPUT_FLAG |
wxSOCKET_LOST_FLAG);
m_sock->Notify(true);
//第二步:连接服务器
wxIPaddress * addr;
wxIPV4address addr4;
addr = &addr4;
// Ask user for server address
wxString hostname = (“localhost”);
addr->Hostname(hostname);
addr->Service(3000);
m_sock->Connect(*addr, false);
//设置TCP连接的工作方式
m_sock->SetFlags(wxSOCKET_WAITALL);
//第三步:向服务器发送数据
unsigned char c = 0xBE;
m_sock->Write(&c, 1);
//第四步:获取服务器的反馈数据
const unsigned char len = 32;
wxCharBuffer buf1(len * 1024), buf2(len * 1024);
m_sock->Read(buf2.data(), len);

//关闭TCP连接
m_sock->Close();
(4)TCP服务器端主要代码
// 第一步:创建socket,设置基本的工作方式
wxSocketServer *m_server;
// Create the address - defaults to localhost:0 initially
IPaddress addr;
addr.Hostname(wxT(“localhost”));//IP
addr.Service(3000);//port
// Create the socket
m_server = new wxSocketServer(addr);
// Setup the event handler and subscribe to connection events
m_server->SetEventHandler(*this, SERVER_ID);
m_server->SetNotify(wxSOCKET_CONNECTION_FLAG);
m_server->Notify(true);
//添加消息响应函数,当有客户端连接过来的响应,或者客户端有数据过来的响应。
BEGIN_EVENT_TABLE(SocketsServerFrame,wxFrame)
EVT_SOCKET(SERVER_ID, SocketsServerFrame::OnServerEvent)
EVT_SOCKET(SOCKET_ID, SocketsServerFrame::OnSocketEvent)
END_EVENT_TABLE()
//当有客户端连接过来的响应
void SocketsServerFrame::OnServerEvent(wxSocketEvent& event)
{
wxString s = _("OnServerEvent: ");
wxSocketBase *sock;

switch(event.GetSocketEvent())
{
case wxSOCKET_CONNECTION :
s.Append((“wxSOCKET_CONNECTION\n”)); break;
default :
s.Append(
(“Unexpected event !\n”)); break;
}
m_text->AppendText(s);

// Accept new connection if there is one in the pending
// connections queue, else exit. We use Accept(false) for
// non-blocking accept (although if we got here, there
// should ALWAYS be a pending connection).

sock = m_server->Accept(false);
if (sock)
{
IPaddress addr;
if ( !sock->GetPeer(addr) )
{
wxLogMessage(“New connection from unknown client accepted.”);
}
else
{
wxLogMessage(“New client connection from %s:%u accepted”,
addr.IPAddress(), addr.Service());
}
}
else
{
wxLogMessage(“Error: couldn’t accept a new connection”);
return;
}
//将该客户端有数据过来的时候,激活响应的数据响应
sock->SetEventHandler(*this, SOCKET_ID);
sock->SetNotify(wxSOCKET_INPUT_FLAG | wxSOCKET_LOST_FLAG);
sock->Notify(true);
}
//客户端有数据过来的响应
void SocketsServerFrame::OnSocketEvent(wxSocketEvent& event)
{
wxString s = _("OnSocketEvent: ");
wxSocketBase *sock = event.GetSocket();

// First, print a message
switch(event.GetSocketEvent())
{
case wxSOCKET_INPUT : s.Append((“wxSOCKET_INPUT\n”)); break;
case wxSOCKET_LOST : s.Append(
(“wxSOCKET_LOST\n”)); break;
default : s.Append(_(“Unexpected event !\n”)); break;
}

m_text->AppendText(s);

// Now we process the event
switch(event.GetSocketEvent())
{
case wxSOCKET_INPUT:
{
// We disable input events, so that the test doesn’t trigger
// wxSocketEvent again.
sock->SetNotify(wxSOCKET_LOST_FLAG);

  // Which test are we going to run?
  unsigned char c;
  sock->Read(&c, 1);

  switch (c)
  {
    case 0xBE: Test1(sock); break;
    case 0xCE: Test2(sock); break;
    case 0xDE: Test3(sock); break;
    default:
      wxLogMessage("Unknown test id received from client");
  }

  // Enable input events again.
  sock->SetNotify(wxSOCKET_LOST_FLAG | wxSOCKET_INPUT_FLAG);
  break;
}
case wxSOCKET_LOST:
{
  m_numClients--;

  // Destroy() should be used instead of delete wherever possible,
  // due to the fact that wxSocket uses 'delayed events' (see the
  // documentation for wxPostEvent) and we don't want an event to
  // arrive to the event handler (the frame, here) after the socket
  // has been deleted. Also, we might be doing some other thing with
  // the socket at the same time; for example, we might be in the
  // middle of a test or something. Destroy() takes care of all
  // this for us.

  wxLogMessage("Deleting socket.");
  sock->Destroy();
  break;
}
default: ;

}
}
//关闭TCP连接
delete m_server;
三.功能测试和演示
1.UDP 数据发送和接收

Step1:在server 选择 UDP test (激活server的UDP功能,注意:只能工作一次)

Step2:在client进行发送数据和接收数据的操作。

客户端需要选择server的名称或IP地址

Step3:观察数据的一次交互过程。(为什么server端的是乱码?)

2.TCP数据发送和接收

进行TCP连接操作,
客户端:TCP菜单/Open seeesion;然后输入相应的服务器地址信息。
客户端可以看到提示:
19:53:02: Trying to connect to localhost:3000
19:53:02: … socket is now connected.
服务器端可以看到提示:
OnServerEvent: wxSOCKET_CONNECTION
19:53:02: New client connection from 127.0.0.1:58015 accepted

进行TCP数据发送/接收测试,
客户端:TCP菜单/Test 3;
客户端可以看到提示:
=== Test 3 begins ===
Sending a large buffer (32K) to the server …done
Receiving the buffer back from server …done
Comparing the two buffers …done
Test 3 passed !
=== Test 3 ends ===
服务器端可以看到提示:
OnSocketEvent: wxSOCKET_INPUT
19:53:07: === Test 3 begins ===
19:53:07: Got the data, sending it back
19:53:07: === Test 3 ends ===

关闭TCP连接,
客户端:TCP菜单/Close session;
服务器端可以看到提示:
OnSocketEvent: wxSOCKET_LOST
20:09:23: Deleting socket.

服务器端可以看到:
19:53:02: Trying to connect to localhost:3000
19:53:02: … socket is now connected.

3.Client URL的测试(访问外网网站)
下面的过程是通过URL 访问百度的网站,可以收到百度的反馈数据。

输入“http://www.baidu.com/” 的百度网站后,可以看到联机的过程和结果。

发布了17 篇原创文章 · 获赞 2 · 访问量 1968

猜你喜欢

转载自blog.csdn.net/qq_23313467/article/details/104143962