一、就先谈谈MFC

MFC是Microsoft Foundation Classes的缩写,是由微软公司提供的一个类库,这是来帮助你完成图形界面的设计和软件平台的开发,但是不管是你软件的开发还是图形界面的设计都都不支持各位去用MFC,看了很多大牛博客都会教导你这个东西操作繁杂,而且不易入门,可以说当时选择在这个平台上做这个软件是一个错误。就我所了解的到现今更加倾向于Qt,也是各种大牛给我的最一致的软件。

二、实现通信我们就必须了解一下什么是SOCKET?

Socket也成为套接字,套接字是支持TCP/IP网络通信的基本操作单元。多个TCP连接或多个应用程序进程可能需要通过同一个TCP协议端口传输数据。为了区别不同的应用程序进程和连接,许多计算机操作系统为应用程序与TCP/IP协议交互提供了称为套接字(Socket)的接口。

上面便是采用SOCKET实现通信的大致流程,当然计算机内部的实现肯不是这么简单,其中会涉及到TCP握手的建立连接和断开连接等等。

三、了解到了SOCKET就必须了解一下SOCKET通信的基本操作:

1.socket()函数

2.bind()函数

3.listrn()函数,connect()函数

4.accept()函数

5.read()函数、write()函数、receive()函数等

6.close()函数

7.TCP三次握手建立连接

8.TCP四次握手释放连接

3.1、socket()函数

socket函数对应于普通文件的打开操作。普通文件的打开操作返回一个文件描述字,而socket()用于创建一个socket()描述符,它唯一标识一个socket.这个socket描述字跟文件描述字一样,后续操作都有用它来进行一些读写操作。

3.2、bind()函数

bind()函数是把一个地址族中的特定地址赋给socket。例如对应AF_INET、AF_INET6就是把一个ipv4或ipv6地址和端口号组合赋给socket.

3.3、listen()、connect()函数

如果作为一个服务器,在调用socket()、bind()之后就会调用listen()来监听这个socket,如果客户端这是调用connect()发出连接请求,服务器就会收到这个请求。

connect()函数则是用来发送连接请求的。

3.4、accept()函数

TCP服务器端依次调用socket()、bind()、listen()之后,就会监听制定的socket地址了。TCP客户端依次调用socket()、connect()之后就向TCP服务器发送了一个连接请求。TCP服务器监听这个请求之后,就会调用accept()函数取接收请求,这样连接就建立好了。之后就可以开始网络I/O操作。

3.5、read()、write()、receive()等函数

当服务器与客户已经建立号连接之后就可以调用网络I/O进行读写操作了,即实现网络中不同进程之间的通信!网络I/O操作有下面几组:

read()/write()

recv()/send()

readv()/writev()

recvmsg()/sendmsg()

recvfrom()/sendto()

3.6、close()函数

在服务器与客户端建立连接后会进行一些读写操作,就要关闭相应的socket()描述字,好比操作完打开的文件要调用fclose关闭打开的文件

其中各种函数的具体参数的设置可以参考http://www.360doc.com/content/18/0902/22/38894361_783383225.shtml这位大牛的博客,关于socket通信的基本原理还是讲的较为清楚的。

3.7、TCP中三次握手建立连接详解:

1.客户方法端向服务器发送一个SYN J

2.服务器向客户端响应一个 SYN K,并对STN J进行确认ACK J+1

3.客户端再向服务端发送一个确认ACK K+1

(1) 服务器监听:服务器并不定位具体客户端的套接字,而是时刻处于监听状态;

(2) 客户端请求:客户端的套接字要描述它要连接的服务器的套接字,提供地址和端口号,然后向服务器套接字提出连接请求;

(3) 连接确认:当服务器套接字收到客户端套接字发来的请求后,就响应客户端套接字的请求,并建立一个新的线程,把服务器端的套接字的描述发给客户端。一旦客户端确认了此描述,就正式建立连接。而服务器套接字继续处于监听状态,继续接收其他客户端套接字的连接请求.

3.8、TCP中四次握手释放连接详解

1.某个应用进程首先调用close主动关闭连接,这时TCP发送一个 FIN M;

2.另一端接收到FIN M之后,执行被动关闭,对这个FIN 进行确认。它的接收也作为文件结束符传递给应用进程,因为FIN的接收意味着该应用进程在这个相应的连接上再也接收不到其他额外的数据

3.一段时间之后,接收到文件结束符的应用进程会调用close()函数进行关闭socket操作,与此同时它的TCP也发送一个FIN N;

4.接收到这个FIN的源发送端的TCP会对它进行确认

四、具体的实现过程

1.图形界面的设计

2.客户端与服务端代码的写进

3.客户端与服务端之间能后实现信息的交互,最终实现局域网聊天

4.当然加入数据库后能实现更多的功能我也算是只是想实现聊天记录被实时送进数据库,然后返回出来被客户读取

5.最终构成了一个聊天软件

在这个整体的实现过程中就主要是信息的交互,这是主要运用到了TCP/IP网络通信,然后就是MFC中按钮的设置,什么可以响应,什么时候无法响应,这些东西都只是运用到MFC中的函数就行,逻辑上面也没有什么难度。

还有就是服务端开启和关闭,点击开启按钮如果已经开启则将其关闭,同时那个显示出来的按钮上信息也会改变,如果没有则开启服务端,然后就是客户端连接服务端,首先判断是否连接,如果连接上了就断开服务器,此后也会进行一系列的客户从服务端移除等等操作,如果没有此时状态判断是没有连接上的话就进行ip地址的读取和匹配,如果匹配成功则代表连接上同时更新聊天成员信息,如果没有匹配失败则显示连接失败信息,至于了客户端和服务端如何连接则是参考上面的3次握手建立TCP连接,断开同样参考上文四次握手释放连接。

然后就是数据库的连接和数据入库了,首先会有一个数据库测试连接,我采用ODBC连接本地的MySQL数据库,测试连接成功是没有任何问题的,如果失败则会显示数据库连接失败,然后就是数据入库的问题,我的数据库只包含三个信息:1. 用户名 2. 发送的信息(str) 3.信息发送的时间(时间通过CTime来实现记录发送信息时的时间记录的),最后就是数据库中的数据读取,如果数据库中数据为空则不返回任何信息,如果有信息则按照上面的顺序依次将数据库中的信息打印出来,以便客户端的客户读取。

4.1、 图形界面设计

服务端图形界面:

// 设置此对话框的图标。  当应用程序主窗口不是对话框时,框架将自动//  执行此操作SetIcon(m_hIcon, TRUE);            // 设置大图标SetIcon(m_hIcon, FALSE);        // 设置小图标// TODO:  在此添加额外的初始化代码//----------------初始化------------------int n;CString noUser = _T("该用户不存在或者未上线");n = WideCharToMultiByte(CP_OEMCP, 0, noUser, -1, NULL, 0, 0, FALSE);m_strNoUser = new char[n];memset(m_strNoUser, 0, n*sizeof(char));WideCharToMultiByte(CP_OEMCP, 0, noUser.GetBuffer(0), n, m_strNoUser, n , 0, FALSE);m_users.AddString(_T("所有人"));m_connect = false;//设置“发送”按钮为不可用m_buttonSend.EnableWindow(FALSE);//----------------------------------------void ClineDlg::OnPaint()
{if (IsIconic()){CPaintDC dc(this); // 用于绘制的设备上下文SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);// 使图标在工作区矩形中居中int cxIcon = GetSystemMetrics(SM_CXICON);int cyIcon = GetSystemMetrics(SM_CYICON);CRect rect;GetClientRect(&rect);int x = (rect.Width() - cxIcon + 1) / 2;int y = (rect.Height() - cyIcon + 1) / 2;// 绘制图标dc.DrawIcon(x, y, m_hIcon);}else{CDialogEx::OnPaint();}
}

客户端图形界面:

// 设置此对话框的图标。  当应用程序主窗口不是对话框时,框架将自动//  执行此操作SetIcon(m_hIcon, TRUE);            // 设置大图标SetIcon(m_hIcon, FALSE);        // 设置小图标// TODO:  在此添加额外的初始化代码//------------------初始化---------------------SetDlgItemText(IDC_USERNAME,m_userName);//设置初始用户列表为只有一个,即“所有人”m_userslist.AddString(_T("所有人"));//设置“发送”按钮为不可用m_buttonSend.EnableWindow(FALSE);//设置“显示聊天记录”的按钮为不可用m_buttonShowHistory.EnableWindow(FALSE);void ClineClientDlg::OnPaint()
{if (IsIconic()){CPaintDC dc(this); // 用于绘制的设备上下文SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);// 使图标在工作区矩形中居中int cxIcon = GetSystemMetrics(SM_CXICON);int cyIcon = GetSystemMetrics(SM_CYICON);CRect rect;GetClientRect(&rect);int x = (rect.Width() - cxIcon + 1) / 2;int y = (rect.Height() - cyIcon + 1) / 2;// 绘制图标dc.DrawIcon(x, y, m_hIcon);}else{CDialogEx::OnPaint();}
}

4.2、客户端与服务端代码

服务端:

//启动/关闭服务器的服务
void ClineDlg::startServer()
{// TODO:  在此添加控件通知处理程序代码CString cport;//获取服务器的端口号GetDlgItemText(IDC_SERVERPORT,cport);//端口号的字符串转换为数字int port = _ttoi(cport);//如果没有填写端口号,则默认的端口号为1111if (port == 0){m_port = 1111;}else{m_port = port;}//如果当前服务器的状态为开启,则关闭服务器if (m_connect){//关闭服务器的socketdelete m_listenSocket;m_listenSocket = NULL;m_connect = false;SetDlgItemText(IDC_BN_SERVER_START, _T("打开服务器"));UpdateEvent(_T("系统关闭服务器."));//关闭控件的只读状态m_editPort.SetReadOnly(FALSE);//设置“发送”按钮为不可用m_buttonSend.EnableWindow(FALSE);return;}//否则就打开服务器m_listenSocket = new CServerSocket();m_listenSocket->m_pDlg = this;m_listenSocket->m_userName = _T("服务器");// 指定对话框为主对话框,不能少了这句?UpdateData(true);// 创建服务器的套接字,IP地址默认本机IPif (!m_listenSocket->Create(m_port)){AfxMessageBox(_T("创建套接字错误!"));m_listenSocket->Close();return;}if (!m_listenSocket->Listen()){AfxMessageBox(_T("监听失败!"));m_listenSocket->Close();return;}m_connect = true;SetDlgItemText(IDC_BN_SERVER_START, _T("关闭服务器"));//更新聊天窗口中的消息UpdateEvent(_T("系统打开服务器."));//将服务器端口号的控件设置为只读状态if(port == 0){m_editPort.SetWindowTextW(_T("1111"));}else {m_editPort.SetWindowTextW(cport);}m_editPort.SetReadOnly(TRUE);//设置“发送”按钮为可用m_buttonSend.EnableWindow(TRUE);
}//接收由客户端发来的消息
void ClineDlg::RecvData(CServerSocket* pSocket)
{char* pData = NULL;pData = new char[1024];memset(pData, 0, sizeof(char)* 1024);UCHAR leng = 0;CString str;if (pSocket->Receive(pData, 1024, 0) != SOCKET_ERROR){str = pData;translateMsg(str, pSocket);}delete pData;pData = NULL;
}//向服务器本身和所有客户端发送str消息
void ClineDlg::SendMSGToEvery(CString str)
{int n;//宽字节转多字节n = WideCharToMultiByte(CP_OEMCP, 0, str, -1, NULL, 0, 0, FALSE);char *pSend = new char[n];//初始化pSendmemset(pSend, 0, n*sizeof(char));WideCharToMultiByte(CP_OEMCP, 0, str.GetBuffer(0), n, pSend, n , 0, FALSE);POSITION nPos = m_clientList.GetHeadPosition();while (nPos){CServerSocket* pTemp = (CServerSocket*)m_clientList.GetNext(nPos);pTemp->Send(pSend, n);}delete pSend;
}//移除已经退出连接的客户端
void ClineDlg::RemoveClient(CServerSocket* pSocket)
{POSITION nPos = m_clientList.GetHeadPosition();POSITION nTmpPos = nPos;//在客户端列表中查找该客户端while (nPos){CServerSocket* pSockItem = (CServerSocket*)m_clientList.GetNext(nPos);//找到了就删除它if (pSockItem->m_hSocket == pSocket->m_hSocket){CString userLeave;userLeave = pSockItem->m_userName;pSockItem->Close();delete pSockItem;int userIndex = m_users.FindString(0,userLeave);m_users.DeleteString(userIndex);m_clientList.RemoveAt(nTmpPos);m_userCount = m_clientList.GetCount();UpdateData(false);userLeave = _T("用户") + userLeave + _T("离开");UpdateEvent(userLeave);userLeave = _T("MUPDATEUSERLIST") + userLeave + _T("离开");//向服务器和所有客户端发送消息,更新服务器和所有客户端的聊天窗口内容SendMSGToEvery(userLeave);return;}nTmpPos = nPos;}CString userList = UPDATEUSERLIST;userList += translateUsersStr();//向服务器和所有客户端发送消息,更新服务器和所有客户端的聊天室内容SendMSGToEvery(userList);
}//更新聊天窗口中的内容
void ClineDlg::UpdateEvent(CString str)
{CString string;// 获取系统当前时间CTime time = CTime::GetCurrentTime();// 用于换行显示日志str += _T("\r\n");// 格式化当前时间string = time.Format(_T("%Y/%m/%d %H:%M:%S  ")) + str;//获取编辑框最后一行索引int lastLine = m_event.LineIndex(m_event.GetLineCount() - 1);//选择编辑框最后一行m_event.SetSel(lastLine+1,lastLine+2,0);//替换所选那一行的内容m_event.ReplaceSel(string);
}//添加新的客户端
void ClineDlg::AddClient()
{CServerSocket *pSocket = new CServerSocket;pSocket->m_pDlg = this;m_listenSocket->Accept(*pSocket);pSocket->AsyncSelect(FD_READ | FD_WRITE | FD_CLOSE);m_clientList.AddTail(pSocket);m_userCount = m_clientList.GetCount();UpdateData(false);
}//拆分字符串并根据字符串提示转发消息给所有客户端或者转发给指定的客户端
void ClineDlg::translateMsg(CString str, CServerSocket* pSocket)
{// 转发数据给所有用户,包括发送数据的用户CString cstr;int calls = str.Find(_T("MEVERY"));//获取具体的内容cstr = str.Right(str.GetLength() - calls - 6);//如果选中的是“所有人”,则给所有人发消息if (calls != -1){//将socket中的userName和具体内容的字符串拼接起来(如userName是“服务器”,则就是“服务器对每个人说:xxxxx”)cstr = pSocket->m_userName + _T("对每个人说:") + cstr;SendMSGToEvery(cstr);}//否则就给指定客户端发消息else{//这里表示如果用户连接了服务器,将发送带有MUSERNAME的字符串消息int userName = str.Find(_T("MUSERNAME"));if (userName != -1){cstr = str.Right(str.GetLength() - userName - 9);pSocket->m_userName = cstr;m_users.AddString(cstr);cstr = _T("用户")+cstr + _T("连接服务器");UpdateEvent(cstr);//给所有客户端包括服务器都发送某某某连接上了服务器的消息SendMSGToEvery(cstr);Sleep(1000);CString userList = UPDATEUSERLIST;userList += translateUsersStr();//更新服务器和所有客户端的聊天室列表SendMSGToEvery(userList);}else{int call = str.Find(_T("M"));cstr = str.Right(str.GetLength() - call -1);if (call != -1){SendMSGToOne(cstr,pSocket->m_userName);}}}
}//服务器发送消息给指定的一个客户端
void ClineDlg::SendMSGToOne(CString str,CString userSendName)
{CString userName;bool flag = false;CServerSocket* pTemp = NULL;CServerSocket* pSendUser = NULL;int cone = str.Find(_T(" "));userName = str.Left(cone);str = str.Right(str.GetLength() - cone);str = userSendName + _T("对你说:") + str;int n;//宽字节转多字节n = WideCharToMultiByte(CP_OEMCP, 0, str, -1, NULL, 0, 0, FALSE);char *pSend = new char[n];memset(pSend, 0, n*sizeof(char));//宽字节转多字节WideCharToMultiByte(CP_OEMCP, 0, str.GetBuffer(0), n, pSend, n , 0, FALSE);POSITION nPos = m_clientList.GetHeadPosition();//查找目标客户端while (nPos){pTemp = (CServerSocket*)m_clientList.GetNext(nPos);//如果找到了目标客户端(接收方)if (userName == pTemp->m_userName){flag = true;pTemp->Send(pSend, n);}//如果找到了发送方if (userSendName == pTemp->m_userName){pSendUser = pTemp;}}//如果没有找到发送方,则默认是服务器给一个指定的客户端发送消息if (!flag){pSendUser->Send(m_strNoUser, strlen(m_strNoUser));}delete pSend;
}void ClineDlg::SendMSG()
{// TODO:  在此添加控件通知处理程序代码CString  msg;//获取消息框中的字符串GetDlgItemText(IDC_EDITMSG, msg);//获取当前选中的用户的下标(比如选中了某个人或者选中了“所有人”)int selectIndex = m_users.GetCurSel();if(selectIndex == -1){MessageBox(_T("请在聊天室中选择发送对象!"));return ;}if(msg == _T("")){MessageBox(_T("请输入要发送的内容!"));return ;}CString usermsg;//获取该下标的字符串名称m_users.GetText(selectIndex, usermsg);if (usermsg == "所有人"){usermsg = _T("MEVERY") + msg;}else{usermsg = _T("M") + usermsg + _T(" ") + msg;}translateMsg(usermsg, this->m_listenSocket);
}

客户端:

void ClineClientDlg::SendMsg()
{// TODO:  在此添加控件通知处理程序代码CString  msg;//获得消息框里的字符串GetDlgItemText(IDC_EDIT_MSG, msg);int selectIndex = m_userslist.GetCurSel();if(selectIndex == -1){MessageBox(_T("请在聊天室中选择发送对象!"));return ;}if(msg == _T("")){MessageBox(_T("请输入要发送的消息内容!"));return ;}CString usermsg;m_userslist.GetText(selectIndex, usermsg);if (usermsg == "所有人"){usermsg = _T("MEVERY") + msg;}else{usermsg = _T("M") + usermsg + _T(" ") + msg;}if (!usermsg.IsEmpty()){//未连接服务器则不执行if (!m_connect){return;}UpdateData(true);GetDlgItemText(IDC_EDIT_MSG, m_DataSend);if (m_DataSend != ""){int n = 0;m_DataSend = usermsg;//通过将宽字节转换成多字节来获得多字节的位数n = WideCharToMultiByte(CP_OEMCP, 0, m_DataSend, -1, NULL, 0, 0, FALSE);char* pBuff = new char[n];//初始化数组memset(pBuff, 0, n);//将宽字节转换成多字节WideCharToMultiByte(CP_OEMCP, 0, m_DataSend.GetBuffer(0), n, pBuff, n, 0, FALSE);//发送消息m_pSock->SendMSG(pBuff, n);}}
}//连接服务器
void ClineClientDlg::ConnectServer()
{// TODO:  在此添加控件通知处理程序代码GetDlgItemText(IDC_USERNAME, m_userName);//如果已经连接,则断开服务器if (m_connect){//关闭并且删除客户端的socketm_connect = false;m_pSock->Close();delete m_pSock;m_pSock = NULL;m_ConPC.SetWindowTextW(_T("连接服务器"));m_buttonSend.EnableWindow(FALSE);m_buttonShowHistory.EnableWindow(FALSE);UpdateData(false);return;}//否则连接服务器else{//在这里创建新的socketm_pSock = new CClientSocket();//创建套接字if (!m_pSock->Create()){AfxMessageBox(_T("创建套接字失败!"));return;}}//获得ip控件的ipBYTE f1, f2, f3, f4;((CIPAddressCtrl*)GetDlgItem(IDC_SERVERIPADDRESS))->GetAddress(f1, f2, f3, f4);m_strServerip.Format(_T("%d.%d.%d.%d"), f1, f2, f3, f4);m_port = GetDlgItemInt(IDC_SERVERPORT);//连接服务器if (!m_pSock->Connect(m_strServerip, m_port)){AfxMessageBox(_T("连接服务器失败!"));return;}else{m_connect = true;int n = 0;CString userName;userName = _T("MUSERNAME") + m_userName;//宽字节转多字节,确定要发送的字符串将占据多少个宽度的charn = WideCharToMultiByte(CP_OEMCP, 0, userName, -1, NULL, 0, 0, FALSE);char* pBuff = new char[n];memset(pBuff, 0, n);//宽字节转多字节,将要发送的字符串转化为字节流WideCharToMultiByte(CP_OEMCP, 0, userName.GetBuffer(0), n, pBuff, n, 0, FALSE);//通过socket发送多字节流连接m_pSock->SendMSG(pBuff, n);m_ConPC.SetWindowTextW(_T("断开服务器"));m_buttonSend.EnableWindow(TRUE);m_buttonShowHistory.EnableWindow(TRUE);UpdateData(false);}
}//更新聊天室列表
void ClineClientDlg::UpdateUsers(CString str, int index)
{str = str.Right(str.GetLength()-strlen("MUPDATEUSERLIST"));CStringArray *strArray = translateUsersStr(str);int size = strArray->GetSize();m_userslist.ResetContent();m_userslist.AddString(_T("所有人"));for (int i = 0; i < size; i++){m_userslist.AddString(strArray->GetAt(i));}
}//通过“|”符号裁切字符串信息
CStringArray* ClineClientDlg::translateUsersStr(CString  str)
{CStringArray *strArray = new CStringArray;int length;CString *user=NULL;while (-1 != str.Find(_T("|") )){//找到了一个“|”length = str.Find(_T("|"));user = new CString();//取“|”左边的字符串*user = str.Left(length);//更新字符串str = str.Right(str.GetLength() - length - 1);//更新数组strArray->Add(*user);}return strArray;
}

我在客户端中定义发送消息的规则为发送消息之前将要发送消息的字符串进行打包(加首部),当消息传送到服务器端的时候服务器解包(去首部)就可以得到消息,还有包括图形界面的参数,文字规则的解读和发送都可以根据自己喜好更改。

4.3、客户端与服务端之间能后实现信息的交互,最终实现局域网聊天

4.4 数据库的连接

/测试连接数据库    m_dataBase.Open(NULL,  false,  false, _T("ODBC;server=172.25.1.135;DSN=summer;UID=root;PWD=123456")  );     if (!m_dataBase.IsOpen())     {       AfxMessageBox(_T("DB open failed!"));       return false;
}

数据库查询数据:

//查询数据库m_historyStr = _T("");CRecordset record(&m_dataBase); int count = 0;  CString str2;  CString userNameFilter;//record.m_strFilter = _T("name='小白'");  userNameFilter.Format(_T("name='%s'"),m_userName);record.m_strFilter = userNameFilter;//my_record.m_strSort = _T("cust_id desc");  record.Open(CRecordset::snapshot  , _T("select * from history"));  record.MoveFirst();//如果数据库为空,则返回//int num = record.GetODBCFieldCount();if(record.IsBOF())  {  return ;  }  CDBVariant varValue;//获得表中全部数据while(!record.IsEOF())  {  record.GetFieldValue(2, str2);  m_historyStr += str2;m_historyStr +=_T("\r\n");record.GetFieldValue((short)0, str2);  m_historyStr += str2;record.GetFieldValue(1, str2);  m_historyStr += str2;m_historyStr +=_T("\r\n");record.MoveNext();  count++;  }  UpdateData(FALSE);
}//每更改一次聊天窗口的内容,就更新数据库对应的聊天记录
void ClineClientDlg::updateDataBase(CString newStr)
{if(m_pSock == NULL){return ;}//获取系统时间//SYSTEMTIME st;   //CString strDate,strTime;   //this->GetLocalTime(&st);   //strDate.Format("%4d-%2d-%2d",st.wYear,st.wMonth,st.wDay);   //strTime.Format("%2d:%2d:%2d",st.wHour,st.wMinute,st.wSecond);CTime curTime;curTime = CTime::GetCurrentTime();CString strCurTime;                 strCurTime.Format(_T("%4d-%2d-%2d %2d:%2d:%2d"), curTime.GetYear(),curTime.GetMonth(), curTime.GetDay(), curTime.GetHour(),curTime.GetMinute(), curTime.GetSecond());CString str;str.Format(_T("insert history value('%s','%s','%s')"),m_userName,newStr,strCurTime);m_dataBase.ExecuteSQL(str);
}

大致也就这样喽,个人比较菜,大牛看到错误望指出,让我加以更正!

基于MFC平台实现SOCKET通信相关推荐

  1. AgileEAS.NET SOA 中间件平台.Net Socket通信框架-完整应用例子-在线聊天室系统-代码解析...

    一.AgileEAS.NET SOA中间件Socket/Tcp框架介绍 在文章AgileEAS.NET SOA 中间件平台.Net Socket通信框架-介绍一文之中我们对AgileEAS.NET S ...

  2. 基于Java NIO的Socket通信

    基于Java NIO的Socket通信 Java NIO模式的Socket通信,是一种同步非阻塞IO设计模式,它为Reactor模式实现提供了基础. 下面看看,Java实现的一个服务端和客户端通信的例 ...

  3. java socket发送定长报文_一个基于TCP协议的Socket通信实例

    原标题:一个基于TCP协议的Socket通信实例 1. 前言 一般接口对接多以http/https或webservice的方式,socket方式的对接比较少并且会有一些难度.正好前段时间完成了一个so ...

  4. AgileEAS.NET SOA 中间件平台.Net Socket通信框架-简单例子-实现简单的服务端客户端消息应答...

    一.AgileEAS.NET SOA中间件Socket/Tcp框架介绍 在文章AgileEAS.NET SOA 中间件平台Socket/Tcp通信框架介绍一文之中我们对AgileEAS.NET SOA ...

  5. 基于Java的TCP Socket通信详解(计算机端/Android手机端)

    TCP Socket通信是一种比较常用的基于连接的网络通信方式.本文通过Java实现TCP Socket通信,并将其用于计算机端.Android手机端,同时做到代码规范化,实现代码最大化复用. 本文代 ...

  6. 创龙基于AM5728平台的PCIe通信案例(一)

    本次PCIe通信案例测试基于AM5728平台,篇幅较长,共分为三部分,分别阐述:AM57x与Artix-7FPGA.AM57x与Kintex-7 FPGA.AM57x与TMS320C66x DSP的P ...

  7. 基于Linux平台的TCP通信并发服务器---在线英语词典项目

    文章目录 前言 一.什么是并发服务器 二.服务器的实现 三.客户端的实现 四.代码测试结果 五.代码测试注意 总结 前言 本文是我在IO进线程.网络编程学习阶段的练习项目.项目基于linux平台,利用 ...

  8. c/c++基于liunx平台tcp协议通信分数据段发送小demo

    引言*:tcp 是网络通信的一种协议,协议的话对于程序员来说就是按照约定的协议编写程序即可,具体编码的话相对于 之前做过的 socket 通信的 demo 来说 socket 通信来说并不会使用全新的 ...

  9. plc 上位机编译算法_基于西门子PLC的Socket通信深度剖析

    对于自控或电气工程师来说,西门子PLC是每个人都非常熟悉的一款PLC品牌:而对于上位机开发工程师来说,Socket通信或TCP/IP协议也是必须要掌握的一种通信方式.西门子的200Smart PLC, ...

最新文章

  1. ASP.NET MVC 过滤器(三)
  2. addonsmaker怎么制作_addonsmaker
  3. 浏览器在线预览pdf、txt、office文件
  4. C语言中的fopen函数
  5. delphi 获取桌面路径
  6. ASP.NET页面间数据传递的方法
  7. svn报错:This error was generated by a custom hook script on the Subversion server.
  8. jquery判断toggle当前状态
  9. 谋求“同股不同权”,旷视赴港上市渐近
  10. 【ElasticSearch 】ElasticSearch监控工具 cerebro
  11. Python实现对于文件的分类
  12. 把我的漫画浏览器后台程序迁移到GAE上了
  13. 强化学习各概念整理(value/policy-based、on/off-policy、model-based/free、offline)
  14. 计算机的网络命令大全,windows常用网络命令图文详解
  15. matlab中断概率仿真,使用Matlab进行误比特率仿真
  16. 淘宝网禁售无证食品和保健品 问题商品将被屏蔽
  17. 采购系统是如何管理供应商的?
  18. Tensorboard无法显示图像
  19. 开箱即用的百度开放域信息抽取的统一框架UIE
  20. Spring Cloud Kubernetes 中文文档

热门文章

  1. 【Python】字节码与dis模块
  2. pytorch c++混编报错 Error checking compiler version for cl: [WinError 2] 系统找 不到指定的文件。
  3. 「镁客·请讲」bitBerg杨坤:冰山下藏着的是VR游戏的未来
  4. android接入即时IM(接入亲加通信云)
  5. 五洲御瓷精彩绽放2020第八届特色酒店案例分享论坛暨十周年庆典
  6. 大数据(Big Data)扫盲
  7. [BZOJ1933][Shoi2007]Bookcase 书柜的尺寸(DP)
  8. 一起来学Flutter: 使用Decoration设置背景
  9. 马云:关于P2P,不要你觉得,我要我觉得。---------王艾老哥
  10. 罗宾斯管理学第13版课后答案