Scoket 多线程范例 TCP UDP Server Client
2016-06-01 13:55
471 查看
来源:VC驿站
<span style="font-size:14px;">/**********核心使用**********/ SOCKET m_Socket; /**********TCP Server 接收线程**********/ static UINT __cdecl ThreadProcTCPServer(LPVOID pParam); UINT CNetworkVideoDlg::ThreadProcTCPServer( LPVOID pParam ) { ASSERT(pParam); sockaddr_in clientAddr = {0}; CNetworkVideoDlg *pThis = (CNetworkVideoDlg *)pParam; pThis->WinSockInit(); pThis->m_serverListenSocket = INVALID_SOCKET; pThis->m_serverListenSocket = socket(AF_INET , SOCK_STREAM , IPPROTO_TCP); if ( pThis->m_serverListenSocket == INVALID_SOCKET ) { AfxMessageBox(_T("新建Socket失败!")); goto __Error_End; } pThis->configParams();//配置IP地址 端口 等 sockaddr_in service; service.sin_family = AF_INET; service.sin_addr.s_addr = INADDR_ANY; //任意本地IP地址 service.sin_port = htons(pThis->m_localPort); if ( bind(pThis->m_serverListenSocket, (sockaddr*)&service, sizeof(sockaddr_in)) == SOCKET_ERROR ) { AfxMessageBox(_T("绑定端口失败!")); goto __Error_End; } if( listen(pThis->m_serverListenSocket, SOMAXCONN) == SOCKET_ERROR ) { AfxMessageBox(_T("监听失败!")); goto __Error_End; } int iLen = sizeof(sockaddr_in); //等待客户端来链接 pThis->m_serverSocket = accept(pThis->m_serverListenSocket, (struct sockaddr *)&clientAddr , &iLen); if (pThis->m_serverSocket == INVALID_SOCKET) { goto __Error_End; } else { CString strState; strState.Format(_T("%s 已经上线"),inet_ntoa(clientAddr.sin_addr)); pThis->SetDlgItemText(IDC_EDIT_STATE, strState); } while(m_bRunFlag) { if ( pThis->SOCKET_Select(pThis->m_serverSocket) ) //检测可读性 { TCHAR szBuf[MAX_BUF_SIZE] = {0}; int iRet = recv(pThis->m_serverSocket, (char *)szBuf, MAX_BUF_SIZE, 0); if ( iRet > 0 ) { //right; pThis->ShowReceiveMsg(szBuf); }else{ //close socket; pThis->ShowReceiveMsg(_T("客户端已下线,请重新开启服务器等待客户端连接!")); break; } } Sleep(500); } __Error_End: if (pThis->m_serverListenSocket != INVALID_SOCKET) { closesocket(pThis->m_serverListenSocket); } if (pThis->m_serverSocket != INVALID_SOCKET) { closesocket(pThis->m_serverSocket); } WSACleanup(); ::PostMessage(pThis->GetSafeHwnd(),MSG_THREAD_SAFE_END,0,0); return TRUE; } /**********TCP Client 接收线程**********/ static UINT __cdecl ThreadProcTCPClient(LPVOID pParam); UINT CNetworkVideoDlg::ThreadProcTCPClient( LPVOID pParam ) { ASSERT(pParam); CNetworkVideoDlg* pThis = (CNetworkVideoDlg*) pParam; pThis->WinSockInit(); pThis->m_clientSocket = INVALID_SOCKET; pThis->m_clientSocket = socket(AF_INET , SOCK_STREAM , IPPROTO_TCP); if ( pThis->m_clientSocket == INVALID_SOCKET ) { AfxMessageBox(_T("新建Socket失败!")); goto __Error_End; } pThis->configParams(); sockaddr_in server; server.sin_family = AF_INET; server.sin_port = htons(pThis->m_destPort); server.sin_addr.s_addr = inet_addr(pThis->m_strIP);//192.168.1.57 "127.0.0.1" if ( connect(pThis->m_clientSocket, (struct sockaddr *)&server, sizeof(struct sockaddr)) == SOCKET_ERROR ) { ShowError(); AfxMessageBox(_T("连接失败,请重试!")); goto __Error_End; }else { //pThis->ShowMsg(_T("连接成功!")); pThis->SetDlgItemText(IDC_EDIT_STATE,_T("连接成功!")); } while(m_bRunFlag) { if ( pThis->SOCKET_Select(pThis->m_clientSocket) ) //检测可读性 { TCHAR szBuf[MAX_BUF_SIZE] = {0}; int iRet = recv(pThis->m_clientSocket, (char *)szBuf, MAX_BUF_SIZE, 0); if ( iRet > 0 )//读取正确 { pThis->ShowReceiveMsg(szBuf); }else //连接已经关闭、重启或中断; { pThis->ShowReceiveMsg(_T("链接已经中断,请重新进行连接!")); break; } } Sleep(500);//存疑 是否需要加??? } __Error_End: if (pThis->m_clientSocket != INVALID_SOCKET) { closesocket(pThis->m_clientSocket); } WSACleanup(); ::PostMessage(pThis->GetSafeHwnd(),MSG_THREAD_SAFE_END,0,0); return TRUE; } /**********UDP Server 接收线程**********/ static UINT __cdecl ThreadProcUDPServer(LPVOID pParam); UINT CNetworkVideoDlg::ThreadProcUDPServer( LPVOID pParam ) { ASSERT(pParam); sockaddr_in clientAddr = {0}; CNetworkVideoDlg *pThis = (CNetworkVideoDlg *)pParam; pThis->WinSockInit(); pThis->m_serverSocket = INVALID_SOCKET; pThis->m_serverSocket = socket(AF_INET , SOCK_DGRAM , 0); if ( pThis->m_serverSocket == INVALID_SOCKET ) { AfxMessageBox(_T("新建Socket失败!")); goto __Error_End; } pThis->configParams(); sockaddr_in service; service.sin_family = AF_INET; service.sin_addr.s_addr = INADDR_ANY; //任意本地IP地址 service.sin_port = htons(pThis->m_localPort); if ( bind(pThis->m_serverSocket, (sockaddr*)&service, sizeof(sockaddr_in)) == SOCKET_ERROR ) { AfxMessageBox(_T("绑定端口失败!")); goto __Error_End; } while(m_bRunFlag) { if ( pThis->SOCKET_Select(pThis->m_serverSocket) ) //检测可读性 { TCHAR szBuf[MAX_BUF_SIZE] = {0}; //int iRet = recv(pThis->m_serverSocket, (char *)szBuf, MAX_BUF_SIZE, 0); //char recvBuf[50]; SOCKADDR addrClient; int len = sizeof(SOCKADDR); int iRet = recvfrom(pThis->m_serverSocket, (char *)szBuf,MAX_BUF_SIZE,0,(SOCKADDR*)&addrClient,&len); if ( iRet > 0 ) //读取正确 { pThis->ShowReceiveMsg(szBuf); sockaddr_in sin; memcpy(&sin, &addrClient, sizeof(sin)); CString strState; strState.Format(_T("来自%s的数据"),inet_ntoa(sin.sin_addr)); pThis->SetDlgItemText(IDC_EDIT_STATE, strState); }else { //close socket; pThis->ShowReceiveMsg(_T("recvfrom failed!")); break; } } Sleep(500); } __Error_End: if (pThis->m_serverSocket != INVALID_SOCKET) { closesocket(pThis->m_serverSocket); } WSACleanup(); ::PostMessage(pThis->GetSafeHwnd(),MSG_THREAD_SAFE_END,0,0); return TRUE; } /**********UDP Client 接收线程**********/ static UINT __cdecl ThreadProcUDPClient(LPVOID pParam); UINT CNetworkVideoDlg::ThreadProcUDPClient( LPVOID pParam ) { ASSERT(pParam); sockaddr_in clientAddr = {0}; CNetworkVideoDlg *pThis = (CNetworkVideoDlg *)pParam; pThis->WinSockInit(); pThis->m_clientSocket = INVALID_SOCKET; pThis->m_clientSocket = socket(AF_INET , SOCK_DGRAM , 0); if ( pThis->m_clientSocket == INVALID_SOCKET ) { AfxMessageBox(_T("新建Socket失败!")); goto __Error_End; } pThis->configParams(); sockaddr_in service; service.sin_family = AF_INET; service.sin_addr.s_addr = INADDR_ANY; service.sin_port = htons(pThis->m_localPort); if ( bind(pThis->m_clientSocket, (sockaddr*)&service, sizeof(sockaddr_in)) == SOCKET_ERROR ) { AfxMessageBox(_T("绑定端口失败!")); goto __Error_End; } while(m_bRunFlag) { if ( pThis->SOCKET_Select(pThis->m_clientSocket) ) //检测可读性 { TCHAR szBuf[MAX_BUF_SIZE] = {0}; //int iRet = recv(pThis->m_serverSocket, (char *)szBuf, MAX_BUF_SIZE, 0); //char recvBuf[50]; SOCKADDR addrClient; int len = sizeof(SOCKADDR); int iRet = recvfrom(pThis->m_clientSocket, (char *)szBuf,MAX_BUF_SIZE,0,(SOCKADDR*)&addrClient,&len); if ( iRet > 0 ) //读取正确 { pThis->ShowReceiveMsg(szBuf); }else { //close socket; pThis->ShowReceiveMsg(_T("recvfrom failed!")); break; } } Sleep(500); } __Error_End: if (pThis->m_clientSocket != INVALID_SOCKET) { closesocket(pThis->m_clientSocket); } WSACleanup(); ::PostMessage(pThis->GetSafeHwnd(),MSG_THREAD_SAFE_END,0,0); return TRUE; } /**********发送范例**********/ void CNetworkVideoDlg::OnBnClickedButtonSend() { if (m_cbTCPUDP.GetCurSel() == 0) //TCP Server { CString strText; GetDlgItemText(IDC_EDIT_SEND, strText); int count = m_listServerSocket.GetCount(); for (int i = 0; i < count;++i) { CClientInfo clientInfo = m_listServerSocket.GetAt(m_listServerSocket.FindIndex(i)); if (!strText.IsEmpty() && SOCKET_Select(clientInfo.m_clientSocket, 100, FALSE)) { send(clientInfo.m_clientSocket, (char *)strText.GetBuffer(), strText.GetLength()*sizeof(TCHAR), 0); SetDlgItemText(IDC_EDIT_SEND, _T("")); } } }else if (m_cbTCPUDP.GetCurSel() == 1)//TCP Client { if (m_clientSocket == INVALID_SOCKET) { AfxMessageBox(_T("请先打开")); return; } CString strText; GetDlgItemText(IDC_EDIT_SEND, strText); if (!strText.IsEmpty() && SOCKET_Select(m_clientSocket, 100, FALSE)) { send(m_clientSocket, (char *)strText.GetBuffer(), strText.GetLength()*sizeof(TCHAR), 0); SetDlgItemText(IDC_EDIT_SEND, _T("")); } }else if (m_cbTCPUDP.GetCurSel() == 2)//UDP Server { if (m_serverSocket == INVALID_SOCKET) { AfxMessageBox(_T("请先打开")); return; } CString strText; GetDlgItemText(IDC_EDIT_SEND, strText); if (!strText.IsEmpty() && SOCKET_Select(m_serverSocket, 100, FALSE)) { configParams(); sockaddr_in destaddr; destaddr.sin_family = AF_INET; destaddr.sin_addr.s_addr = inet_addr(m_strIP); destaddr.sin_port = htons(m_destPort); sendto(m_serverSocket, (char *)strText.GetBuffer(), strText.GetLength()*sizeof(TCHAR), 0, (struct sockaddr*)&destaddr,sizeof(destaddr)); SetDlgItemText(IDC_EDIT_SEND, _T("")); } }else if (m_cbTCPUDP.GetCurSel() == 3)//UDP Client { if (m_clientSocket == INVALID_SOCKET) { AfxMessageBox(_T("请先打开")); return; } CString strText; GetDlgItemText(IDC_EDIT_SEND, strText); if (!strText.IsEmpty() && SOCKET_Select(m_clientSocket, 100, FALSE)) { //send(m_clientSocket, (char *)strText.GetBuffer(), strText.GetLength()*sizeof(TCHAR), 0); configParams(); sockaddr_in destaddr; destaddr.sin_family = AF_INET; destaddr.sin_addr.s_addr = inet_addr(m_strIP);; //任意本地IP地址 destaddr.sin_port = htons(m_destPort); sendto(m_clientSocket, (char *)strText.GetBuffer(), strText.GetLength()*sizeof(TCHAR), 0, (struct sockaddr*)&destaddr,sizeof(destaddr)); SetDlgItemText(IDC_EDIT_SEND, _T("")); } } } /**********辅助函数**********/ // 完成SOCKET的库的初始化 版本为2.2 最新 BOOL WinSockInit(void) { WSADATA data = {0}; if(WSAStartup(MAKEWORD(2, 2), &data)) //完成SOCKET的库的初始化 版本为2.2 最新 return FALSE; if ( LOBYTE(data.wVersion) !=2 || HIBYTE(data.wVersion) != 2 ){ WSACleanup(); return FALSE; } return TRUE; } //封装Select函数 ; 参数:1.待查询的SOCKET;2.查询时间毫秒;3.TRUE检测可读性 FALSE检测可写性 BOOL SOCKET_Select( SOCKET hSocket, int nTimeOut = 100, BOOL bRead = TRUE ) { fd_set fdset; timeval tv; FD_ZERO(&fdset); FD_SET(hSocket, &fdset); nTimeOut = nTimeOut > 1000 ? 1000 : nTimeOut; //检测时间时间不超过1秒 tv.tv_sec = 0; tv.tv_usec = nTimeOut; int iRet = 0; if ( bRead ) { iRet = select(0, &fdset, NULL , NULL, &tv); //检测可读性 }else { iRet = select(0, NULL , &fdset, NULL, &tv); //检测可写性 } if(iRet <= 0) //有错误发送 或者 该hSocket不具备可读写性 { return FALSE; } else if (FD_ISSET(hSocket, &fdset)) //该hSocket具备可读写性 { return TRUE; } return FALSE; } // 将字符串显示到CEdit框的末尾 void ShowReceiveMsg(CString strMsg) { m_editReceive.SetSel(-1, -1); //选择最末尾 m_editReceive.ReplaceSel( strMsg+_T("\r\n")); } /**********补充说明**********/ TCP编程的服务器端一般步骤是: 1、创建一个socket,用函数socket(); 2、设置socket属性,用函数setsockopt(); * 可选 3、绑定IP地址、端口等信息到socket上,用函数bind(); 4、开启监听,用函数listen(); 5、接收客户端上来的连接,用函数accept(); 6、收发数据,用函数send()和recv(),或者read()和write(); 7、关闭网络连接; 8、关闭监听; TCP编程的客户端一般步骤是: 1、创建一个socket,用函数socket(); 2、设置socket属性,用函数setsockopt();* 可选 3、绑定IP地址、端口等信息到socket上,用函数bind();* 可选 4、设置要连接的对方的IP地址和端口等属性; 5、连接服务器,用函数connect(); 6、收发数据,用函数send()和recv(),或者read()和write(); 7、关闭网络连接; UDP编程的服务器端一般步骤是: 1、创建一个socket,用函数socket(); 2、设置socket属性,用函数setsockopt();* 可选 3、绑定IP地址、端口等信息到socket上,用函数bind(); 4、循环接收数据,用函数recvfrom(); 5、关闭网络连接; UDP编程的客户端一般步骤是: 1、创建一个socket,用函数socket(); 2、设置socket属性,用函数setsockopt();* 可选 3、绑定IP地址、端口等信息到socket上,用函数bind();* 可选 4、设置对方的IP地址和端口等属性; 5、发送数据,用函数sendto(); 6、关闭网络连接; /**********补充说明**********/
//设置系统接收缓存
int nRecvBuf = MAX_BUF_SIZE;setsockopt(pMP->m_socket,SOL_SOCKET,SO_RCVBUF,(const char*)&nRecvBuf,sizeof(int));
</span>
相关文章推荐
- 几种Web服务器比较-(Apache、IIS、Lighttpd、Nginx、LiteSpeed、Zeus
- BP神经网络
- ios开发网络篇—数据安全
- 关于Linux网络程序的一些小问题
- java发送http的get、post请求[转]
- qt tcp socket简单的通信程序
- 简单版Java网络爬虫的实现
- HTTP 状态码
- Https双向认证客户端请求方式
- 跨平台高效率Lua网络库 ( 同步形式的API ,底层是异步非阻塞)
- 虚拟机的三种网络模式
- iOS RSA的网络安全模型、iOS签名机制总结(登录、token安全、签名)
- HTTP协议详解
- ios开发网络篇—Get请求和Post请求
- Java网络编程——基于UDP的Socket编程
- [置顶] XListView上拉刷新下拉加载(网络请求json)
- HTTP遇到的安全问题&&HTTPS解决的问题
- iOS-HTTP 请求方式: GET和POST的比较
- HttpUtils解析xml数据
- Linux几种网络连接模式