• 基于TCP(面向连接)的Socket编程


    基于TCP(面向连接)的Socket编程

    一、客户端:

    1、打开一个套接字(Socket);

    2、发起连接请求(connect);

    3、如果连接成功,则进行数据交换(read、write、send、recv);

    4、数据交换完成,关闭连接(shutdown、close);

    二、服务器端:

    1、打开一个套接字(Socket);

    2、将套接字绑定到服务器地址上(bind);

    3、指定套接字为服务器套接字(listen),做好连接请求准备;

    4、等待连接请求(connect);

    5、如果连接请求到,则连接建立,进行数据交换(read、write、send、recv);

    6、数据交换完成,关闭连接(shutdown、close);

    基于UDP(面向无连接)的Socket编程

    一、客户端服务器端:

    1、打开一个套接字(Socket);

    2、将套接字绑定到指定的服务器地址和端口上(bind);

    3、进行数据交换(read、write、send、recv);

    4、数据交换完成,关闭连接(shutdown、close);

    三、MFC对Socket的支持:

    1、创建CAsyncSocket对象;

    2、发送接收数据报(SendTo、RecvFrom);

    3、连接服务器(Connect);

    4、接收连接(Listen);

    5、发送和接收流式数据(Send、Receive);

    6、关闭套接字(Close);

    7、差错处理(GetLastError)。

    四、实例:网络聊天工具

         客户端:

    1、。。。。

    2、利用类向导重载CAsyncSocket类,生成新的MySocket类。。

    3、利用类向导重载CAsyncSocket的OnReceive(int nErrorCode)和OnSend(int nErrorCode)、OnConnect(int nErrorCode)函数。

    void MySocket::OnReceive(int nErrorCode)

    {

           // TODO: Add your specialized code here and/or call the base class

           //获取对话框指针

           CTestApp*pApp=(CTestApp*)AfxGetApp();

           CTestDlg*pDlg=(CTestDlg*)pApp->m_pMainWnd;

           //往编辑框中插入消息

           char *pbuf=new char[4096];

           int ibufsize=4096;

           int ircvd;

           CString strrecvd;

           ircvd=Receive(pbuf,ibufsize);

           if(ircvd==SOCKET_ERROR)

           {

                  pDlg->MessageBox("SOCKET_ERROR");

           }

           else

           {

                  pbuf[ircvd]=NULL;      

                  pDlg->m_recmsg+="服务器:";

                  pDlg->m_recmsg+=pbuf;     

                  pDlg->m_recmsg+=" ";

                  pDlg->RefreshScreen();

           }

           delete pbuf;

           CAsyncSocket::OnReceive(nErrorCode);

    }

    void MySocket::OnSend(int nErrorCode)

    {

           // TODO: Add your specialized code here and/or call the base class

           CAsyncSocket::OnSend(nErrorCode);

    }

    void MySocket::OnConnect(int nErrorCode)

    {

           // TODO: Add your specialized code here and/or call the base class

           CTestApp*pApp=(CTestApp*)AfxGetApp();

           CTestDlg*pDlg=(CTestDlg*)pApp->m_pMainWnd;

           int iResult=nErrorCode;

           CString buffer;

           int namelen;

           if(iResult!=0)

           {

                  buffer.Format("连接服务器失败。 ");

                  pDlg->m_recmsg+=buffer;

           }

           else

           {

                  namelen=sizeof(sockaddr_in);

                  buffer.Format("成功连接到服务器 %s:%d. ",pDlg->m_ipstr,pDlg->m_port);

                  pDlg->m_recmsg+=buffer;

                  pDlg->GetDlgItem(IDC_SEND)->EnableWindow(TRUE);

                  pDlg->GetDlgItem(IDOK)->EnableWindow(TRUE);

           }

           pDlg->RefreshScreen();

           CAsyncSocket::OnConnect(nErrorCode);

    }

    4、在C*Dlg类中

    头文件中:

    #include "MySocket.h"

           MySocket m_socket;

           CString m_ipstr;

    .CPP文件中:

    void CTestDlg::OnSend()

    {

           // TODO: Add your control notification handler code here

           int ilen;

           int isent;

           UpdateData(TRUE);

           if(m_msg!="")

           {

                  ilen=m_msg.GetLength ();

                  isent=m_socket.Send(LPCTSTR(m_msg),ilen);

                  if(isent==SOCKET_ERROR)

                  {

                         MessageBox("连接失败,请重试!");

                  //     connect=false;

                  }

                  else

                  {

                         m_recmsg+="客户机:"+m_msg;

                         m_recmsg+=" ";

                         UpdateData(FALSE);

                  }

           }

    }

    void CTestDlg::RefreshScreen()

    {

           UpdateData(false);

    }

    void CTestDlg::OnConnect()

    {

           if (!AfxSocketInit())

           {

                  AfxMessageBox("IDP_SOCKETS_INIT_FAILED");

                  return ;

           }

           GetDlgItemText(IDC_IPADDRESS1,m_ipstr);

           m_socket.m_hSocket=INVALID_SOCKET;

           UpdateData(true);

           BOOL flag=m_socket.Create();

           if(!flag)

           {

                  AfxMessageBox("SOCKET ERROR");

                  return;

           }

           m_socket.Connect(m_ipstr,m_port);

    }

    void CTestDlg::OnOK()

    {

           // TODO: Add extra validation here

           m_socket.Close();

           CDialog::OnOK();

    }

              服务器端:

    1、。。。。

    2、利用类向导重载CAsyncSocket类,生成新的MySocket类。。

    3、利用类向导重载CAsyncSocket的OnReceive(int nErrorCode)和OnSend(int nErrorCode)函数。

    void MySocket::OnReceive(int nErrorCode)

    {

           // TODO: Add your specialized code here and/or call the base class

           CTestApp*pApp=(CTestApp*)AfxGetApp();

           CTestDlg*pDlg=(CTestDlg*)pApp->m_pMainWnd;

           //往列表框中插入消息

           char *pbuf=new char[4096];

           int ibufsize=4096;

           int ircvd;

           CString strrecvd;

           ircvd=Receive(pbuf,ibufsize);

           if(ircvd==SOCKET_ERROR)

           {

                  pDlg->MessageBox("SOCKET_ERROR");

           }

           else

           {

                  pbuf[ircvd]=NULL;

                  pDlg->m_msg+="客户机:";

                  pDlg->m_msg+=pbuf;

                  pDlg->m_msg+=" ";

                  pDlg->RefreshScreen();

           }

           delete pbuf;

           CAsyncSocket::OnReceive(nErrorCode);

    }

    void MySocket::OnSend(int nErrorCode)

    {

           // TODO: Add your specialized code here and/or call the base class

           CAsyncSocket::OnSend(nErrorCode);

    }

    4、新建MyServerSocket类,并添加MySocket * m_socket;即接收请求后的套接字指针。

           MySocket * m_socket;

    void CMyServerSocket::OnAccept(int nErrorCode)

    {

           // TODO: Add your specialized code here and/or call the base class

           CTestApp*pApp=(CTestApp*)AfxGetApp();

           CTestDlg*pDlg=(CTestDlg*)pApp->m_pMainWnd;

           //显示连接消息

           pDlg->m_msg="客户机连接到服务器";

           pDlg->m_msg+=" ";

           pDlg->RefreshScreen();

           pDlg->GetDlgItem(IDC_SEND)->EnableWindow(TRUE);

           pDlg->GetDlgItem(IDOK)->EnableWindow(TRUE);

           MySocket* psocket=new MySocket();

           if(Accept(*psocket))

           {

                  psocket->AsyncSelect(FD_READ);

                  m_socket=psocket;

           }

           else

           {

                  delete psocket;

           }    

           CAsyncSocket::OnAccept(nErrorCode);

    }

    5、C*Dlg类中

    void CTestDlg::RefreshScreen()

    {

           UpdateData(false);

    }

    void CTestDlg::OnListen() //创建服务器

    {

           // TODO: Add your control notification handler code here

           UpdateData(true);

           if (!AfxSocketInit())

           {

                  AfxMessageBox("IDP_SOCKETS_INIT_FAILED");

                  return ;

           }

           BOOL flag=m_serversocket.Create(m_port);

           if(!flag)

           {

                  AfxMessageBox("SOCKET ERROR");

                  return;

           }

           flag=m_serversocket.Listen(1);

           if(!flag)

           {

                  AfxMessageBox("SOCKET ERROR");

                  return;

           }

           SetDlgItemText(IDC_LISTEN,"正在监听");

    }

    void CTestDlg::OnSend()

    {

           // TODO: Add your control notification handler code here

           int ilen;

           int isent;

           UpdateData(TRUE);

           if(m_sendmsg!="")

           {

                  ilen=m_sendmsg.GetLength ();

                  isent=m_serversocket.m_socket->Send(LPCTSTR(m_sendmsg),ilen);

                  if(isent==SOCKET_ERROR)

                  {

                         MessageBox("连接失败,请重试!");

                  }

                  else

                  {

                         m_msg+="服务器:"+m_sendmsg;

                         m_msg+=" ";

                         UpdateData(FALSE);

                  }

           }

    }

    void CTestDlg::OnOK()

    {

           // TODO: Add extra validation here

           m_sendmsg="服务器退出";

           UpdateData(false);

           OnSend();

           m_serversocket.Close();

           CDialog::OnOK();

    }

  • 相关阅读:
    匿名对象、栈空间和堆空间,String的两种实例化方式的比较,"=="和"equals()"的区别
    间接调用父类私有成员方法、通过抽象类可以达到不需要实现接口所有方法的目的
    this关键字、构造快和静态块
    java可变参数的支持和foreach输出
    java-循环结构体
    switch和if else的区别和应用
    作用域对象
    JavaWeb1
    JavaScript 表单编程
    好久不见
  • 原文地址:https://www.cnblogs.com/liaocheng/p/4243469.html
Copyright © 2020-2023  润新知