MFC 车牌识别 小学期作业 part4

来源:互联网 发布:apache ab get参数 编辑:程序博客网 时间:2024/05/01 21:22

part6 具体(5) 网络通信(windows 套接字 MFC的 CSocke类)

socket(套接字)是现在常用的网络通信的方法,每一种语言都规定了自己的套接字的类,方法和使用规则,但大体上他们都是一样的。
分类的话有TCP和UDP,TCP是接收到一方发送消息,需得到另一方的确认信息才会继续下一步工作的一种协议,而UDP这是发了之后,完全不管对方接不接受得到,就自顾自地下一步了,所以说TCP安全可靠一点,但慢,UDP不可靠,但是速度快。

MFC自己封装了一个socket的类,叫Csocket,是一种TCP的协议做这个作业的时候着急,没好好找资料,我只会一种是同步阻塞式的代码,效率低。软件在开始监听后会阻塞,进入假死状态,和不好用,后来在网上查到可以用多线程解决这个问题,自己摸索了一下,结果虽然没有达到期望的最大值,但解决了假死的问题。

以下就是我不够专业,但是亲身经历的网络通信的知识。

首先是TCP为了安全可靠的一个规定;三次握手
即客户端发送一次信息到服务端,服务端确认,回传信息给客户端,客户端再传递信息给服务端的这样必经过程的一个规定。

用MFC的Csocket类的代码说的话,就是几个函数。
首先,在建立工程的时候就要选择使用windows套接字,否则还要自己在MyProjectapp的InitInstance()函数里加入
if (!AfxSocketInit())
    {
        AfxMessageBox(_T("windows socket initialization failed"));
        return FALSE;
    }
这段。

以下是过程:行文顺序按照CSoket的三次握手顺序。

一、代表服务端:

二、代表客户端:



一、服务端:

一、1.创建一个CScoket的对象,因为是服务端,所以必须要指定IP和端口,使用这个函数的一个重载
mySerCSocket.Create(80,1,L"127.127.127.127");
说明:第一个参数:端口;第二个:连接方式,一般是1;第三个:IP地址;返回值表明是否创建成功。
一、2.监听是否有客户端连接进来,使用函数mySerCSocket.Listen();
说明:参数,默认为5,返回值表明是否有客户端连接。这个函数是阻塞的,没有连接的话会卡死在这里。

二、客户端:

二、1.创建一个CSocket的对象,客户端创建不需要有参数。myCliCSocket.Create();
二、2.连接服务端myCliCSocket.Connect(L"127.127.127.127",80);
说明:第一个参数:ip;第二个参数:端口;返回值表明是否连接成功。

服务端:

一、3.如果监听发现有客户端连接,进入下一步,接收,使用函数mySerCSocket.Accept(Csocket rec);
说明:参数:一个CSocket的对象,用于处理已连接的客户端,而mySerCSocket会继续监听新的客户端连接,不管这一个已连接的了;返回值表示是否成功。这个函数也是阻塞的,没有接收到会卡死。

客户端:

二、3.如果连接成功的话,就要传数据了,使用函数myCliCSocket.Send(str,1024);
说明:参数一:发送的字符串;参数二:字符串的长度;返回值表示成功发送的字符串。

服务端:

二、4.服务端接收数据,使用函数mySerCSocket.Receive(str,1024);
说明:第一个参数:接受用到的字符串;第二个参数要接受的字符串长度;返回值表示成功接受的字符串大小。该函数阻塞。

发送完后关闭套接字:

客户端:

一、4.使用函数myCliCSocket.Close();

服务端:

二、5.使用函数mySerCSocket.Close();


一个实例:

服务端代码,写在一个Button的单击事件里:


void CSerDlg::OnBnClickedButtonser()
{
    // TODO: 在此添加控件通知处理程序代码
if(!mySerCSocket.Create(800,1,L"127.127.127.127"))
{
MessageBox(_T("创建失败"));//创建失败给出提示     //_T("")、L""均表示宽字符,VS加入了Unicode字符集后引入的,中文要加他们。
}
if(mySerCSocket.Listen())
{
CSocket recCSocket;
int n=0;
mySerCSocket.Accept(recCSocket);
char *str=new char[1024];
n=recCSocket.Receive(str,1024);//字符串接收不到1024,到哪儿截至用n记录下来
str[n]='\0';//将字符串最后截断,避免乱码出现

MessageBox((CString)str);
}
else MessageBox(_T("监听失败"));
mySerCSocket.Close();
}


客户端代码,写在一个Button里:

void CCliDlg::OnBnClickedButtoncli()
{
    // TODO: 在此添加控件通知处理程序代码
    if(!myCliCSocket.Create())
    {
    MessageBox(_T("创建失败"));//创建失败给出提示
    }
    if(myCliCSocket.Connect(L"127.127.127.127",800))
    {
    char* str="hello world!";
    if(!myCliCSocket.Send(str,30))
    {
    MessageBox(_T("发送失败"));
    }
    }
    else MessageBox(_T("连接失败"));
    myCliCSocket.Close();
}

以上内容完成了MFC下CSocket的基本使用,但我们发现这种方式的使用得到的网络连接是阻塞式的,服务端接收不到信息会假死,怎么办?
网上查了查,说是要用多线程解决,我对这个也尝试了一下。


多线程初试(未完整版)//没有完整版,我不会(摊手)


在需要开启新线程的函数里加入如下语句:
Socket temp;
temp=mySerCSocket.Detach();
AfxBeginThread(Thread,this);
mySerSocket.Attach(temp);

大致意思是先将当前关于网络通信的线程解除关联(别问我什么关联,我不知道),然后开启新线程,也就是一个函数Thread,然后再次回来绑定线程(这里有一个问题,当我用断点测试的时候发现,这里的函数不是按顺序执行的,到AfxBeginThread(Thread,this)后程序不会进入Thread,而是继续向下运行,该函数运行完才进入Thread)。

相应的,我们需要写一下Thread的函数,这是一个与线程有关的函数,格式有要求,

static UINT Thread(LPVOID   p) //格式必须是这样,其中p是任意类型指针,在函数内被转化成窗口类的指针
{
///////初始化socket///////////////
    if (!AfxSocketInit())
    {
        MessageBox(NULL,L"Socket Init Error: AfxSocketInit Error!",NULL,MB_OK);
        return FALSE;
 
    }
    /////////////传入指针/////////////
    CSocketSerDlg* dlg=(CSocketSerDlg*)p;
    CSocket msock;
    msock.Create();
    ////////////////获得句柄///////////////////
    msock.Attach(dlg->mySerCSocket);
}


这样子用可以达到界面不假死的效果,但不可以同时接受多个请求,所以是不完整版。



////////////////////////////////////////////////////////////////////////////////////////

至此,关于车牌识别的发送端的东西就全部写完了,附上车牌识别发送端的下载地址:

车牌识别 发送端


0 0
原创粉丝点击