现在可以实现同步方式,
但是一端掉线,另外一端没有接收到相关消息;
并且在recv的时候会一直阻塞;想通过Select方式实现非阻塞,并且一端掉线后,
另外一端可以及时收到相关消息,作出断开SOCKET等相关操作;请熟悉的朋友帮忙介绍下,谢谢
但是一端掉线,另外一端没有接收到相关消息;
并且在recv的时候会一直阻塞;想通过Select方式实现非阻塞,并且一端掉线后,
另外一端可以及时收到相关消息,作出断开SOCKET等相关操作;请熟悉的朋友帮忙介绍下,谢谢
// 封装SOCKET操作类的头文件 #pragma comment(lib,"ws2_32.lib") #pragma pack(1)extern BOOL myInitSocket(); //初始化Socket相关的库
extern BOOL myBindSocket(SOCKET &sListen,int iPort);
extern int mySendDataToCli(SOCKET sockClient,char *msgToClient);
extern BOOL myLoop(int iFlag);#pragma pack()
/////////////////////////////////////////////////////// mySocketManager.cpp:
// 封装SOCKET操作
//////////////////////////////////////////////////////////////////////#include "stdafx.h"
#include "myMFCServer.h"
#include "mySocketManager.h"//初始化SOCKET相关的库
BOOL myInitSocket()
{
WSADATA wsadata;
if(WSAStartup(MAKEWORD(2,2),&wsadata))
{
return FALSE;
}
return TRUE;
}//绑定Socket,并启动监听
BOOL myBindSocket(SOCKET &sListen,int iPort)
{
SOCKET serverListen = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
if (INVALID_SOCKET == serverListen)
{
return FALSE;
}
SOCKADDR_IN sin;
sin.sin_family = AF_INET;
sin.sin_port = htons(iPort);
sin.sin_addr.S_un.S_addr = INADDR_ANY;
if (SOCKET_ERROR == bind(serverListen,(SOCKADDR*)&sin,sizeof(sin)))
{
return FALSE;
}
if (SOCKET_ERROR == listen(serverListen,2))
{
return FALSE;
}
sListen = serverListen;
return TRUE;
}//向客户端发包
int mySendDataToCli(SOCKET sockClient,char *msgToClient)
{
int len = 0;
if (strlen(msgToClient)>0)
{
len = send(sockClient,msgToClient,strlen(msgToClient),0);
}
return len;
}//循环收发数据包
BOOL myLoop(int iFlag)
{
BOOL bRet = myInitSocket();
if (FALSE == bRet)
{
AfxMessageBox("SOCKET库初始化失败");
return FALSE;
}
SOCKET myListenSocket;
bRet = myBindSocket(myListenSocket,4567);
if (FALSE == bRet)
{
AfxMessageBox("监听失败");
return FALSE;
}
SOCKADDR_IN remoteAddr;
int nAddrLen = sizeof(remoteAddr);
SOCKET sClient;
char szText[] = "Hello Client!\r\n";
while (iFlag) //标记线程是否退出
{
sClient = accept(myListenSocket,(SOCKADDR*)&remoteAddr,&nAddrLen);
if (INVALID_SOCKET == sClient)
{
continue;
}
int len = mySendDataToCli(sClient,szText);
char reevBuf[256]; //没有数据可接收的话,会在这里一直阻塞
len= recv(sClient,reevBuf,256,0);
reevBuf[len] = '\0';
if (len > 0)
{
CString strRecvMsg = "客户端发来的消息";
strRecvMsg.Insert(strRecvMsg.GetLength(),reevBuf);
AfxMessageBox(strRecvMsg );
}
else
{
AfxMessageBox("接受客户端数据包失败");
}
}
closesocket(sClient);
closesocket(myListenSocket);
return TRUE;
}////////////////////////////////////////////////// myMFCServerDlg.h
// MFC窗体头文件class CMyMFCServerDlg : public CDialog
{
// Implementation
public:
//跟线程相关的参数
static int bFlag;
HANDLE hThread;
DWORD threadID;
static DWORD WINAPI ThreadProc(void* pObj);
bool Start(CMyMFCServerDlg* pObj);
};///////////////////////////////////////////////// myMFCServerDlg.cpp
// MFC窗体源文件#include "stdafx.h"
#include "myMFCServer.h"
#include "myMFCServerDlg.h"//封装SOCKET操作的类
#include "mySocketManager.h"//#include "winsock2.h"
#pragma comment(lib,"ws2_32.lib") //线程是否退出的标记
int CMyMFCServerDlg::bFlag = 1; //启动服务
void CMyMFCServerDlg::OnButton1()
{
hThread = CreateThread(NULL,0,ThreadProc,this,0,&threadID);
}//子线程入口函数
DWORD WINAPI CMyMFCServerDlg::ThreadProc(void* pObj)
{
CMyMFCServerDlg* pThis = (CMyMFCServerDlg*)pObj;
pThis->Start(pThis);
return 0;
} //子线程功能函数
bool CMyMFCServerDlg::Start(CMyMFCServerDlg* pObj)
{
myLoop(bFlag);
AfxMessageBox("客户端子线程退出循环");
return TRUE;
} //停止服务
void CMyMFCServerDlg::OnButton2()
{
CMyMFCServerDlg::bFlag = 0;
if (hThread != NULL)
{
//等待线程正常退出
WaitForSingleObject(hThread,2000);
if (hThread != NULL)
{
CloseHandle(hThread);
}
}
DWORD m;
GetExitCodeThread(hThread,&m);
if ( m == STILL_ACTIVE )
{ //强制关闭线程
TerminateThread(hThread,m);
}
hThread = NULL;
}
// 封装SOCKET操作类的头文件 #pragma comment(lib,"ws2_32.lib") #pragma pack(1)extern BOOL myInitSocket(); //初始化Socket相关的库
extern BOOL myInitSocket(SOCKET &s,SOCKADDR_IN & servAddr,CString strIP,int iPort);
extern BOOL myConnShuJuShouFa(SOCKET s,SOCKADDR_IN addr);
extern int mySendDataToServer(SOCKET sockClient,char *msgToClient);
extern BOOL myLoop(int iFlag);#pragma pack()/////////////////////////////////////////////////
// mySocketManager.cpp:
// 封装SOCKET操作
/////////////////////////////////////////////////#include "mySocketManager.h"//初始化Socket相关的库
BOOL myInitSocket()
{
WSADATA wsadata;
if(WSAStartup(MAKEWORD(2,2),&wsadata))
{
return FALSE;
}
return TRUE;
}//创建SOCKET
BOOL myInitSocket(SOCKET &s,SOCKADDR_IN & servAddr,CString strIP,int iPort)
{
SOCKET newSocket = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
if (INVALID_SOCKET == newSocket)
{
return FALSE;
}
SOCKADDR_IN sAddr;
sAddr.sin_family = AF_INET;
sAddr.sin_port = htons(iPort);
sAddr.sin_addr.S_un.S_addr = inet_addr(strIP);
s = newSocket;
servAddr = sAddr;
return TRUE;
}//连接服务器
BOOL myConnShuJuShouFa(SOCKET s,SOCKADDR_IN addr)
{
int connSerResult = connect(s,(SOCKADDR*)&addr,sizeof(addr));
if (-1 == connSerResult)
{
return FALSE;
}
return TRUE;
}//向服务器端发包
int mySendDataToServer(SOCKET sockClient,char *msgToClient)
{
int len = 0;
if (strlen(msgToClient)>0)
{
len = send(sockClient,msgToClient,strlen(msgToClient),0);
}
return len;
}//循环向服务器收发数据包
BOOL myLoop(int iFlag)
{
BOOL bRet = myInitSocket();
if (FALSE == bRet)
{
AfxMessageBox("SOCKET库初始化失败");
return FALSE;
}
SOCKET mySocket;
SOCKADDR_IN addr; //设置连接服务器的IP地址和端口
bRet = myInitSocket(mySocket,addr,"192.168.1.2",4567);
if (FALSE == bRet)
{
AfxMessageBox("客户端Socket创建失败");
return FALSE;
}
bRet = myConnShuJuShouFa(mySocket,addr);
if (FALSE == bRet)
{
AfxMessageBox("连接服务器失败");
return FALSE;
}
char recvBuf[256];
char sendBuf[256];
memset(sendBuf,0,256);
memcpy(sendBuf,"Hello,Server",strlen("Hello,Server")+1);
int nRecv;
int nSend;
//iFlag用来标记是否退出死循环
while (iFlag)
{
//没有数据的话,会一直阻塞
nRecv = recv(mySocket,recvBuf,256,0);
recvBuf[nRecv] = '\0';
if (nRecv >0)
{
CString strRecv = recvBuf;
strRecv = "Server发来的包:\r\n" +strRecv;
AfxMessageBox(strRecv);
}
else
{
AfxMessageBox("接收服务器发来的包失败");
}
nSend = mySendDataToServer(mySocket,sendBuf);
if (nSend <1)
{
AfxMessageBox("向服务器发包失败");
}
}
return TRUE;
}
//////////////////////////////////////// xinlingcaijiDlg.h
// MFC窗体头文件class CXinlingcaijiDlg : public CDialog
{
// Implementation
public:
//跟线程相关的参数
static int bFlag;
HANDLE hThread;
DWORD threadID;
static DWORD WINAPI ThreadProc(void* pObj);
bool Start(CXinlingcaijiDlg* pObj);
};///////////////////////////////////////////
// xinlingcaijiDlg.cpp
// MFC窗体源文件 #include "stdafx.h"
#include "xinlingcaiji.h"
#include "xinlingcaijiDlg.h"//SOCKET操作类
#include "mySocketManager.h"//线程是否退出的标记
int CXinlingcaijiDlg::bFlag = 1; //启动线程,向服务器循环收发数据包
void CXinlingcaijiDlg::OnButton1()
{
hThread = CreateThread(NULL,0,ThreadProc,this,0,&threadID);
}//子线程入口函数
DWORD WINAPI CXinlingcaijiDlg::ThreadProc(void* pObj)
{
CXinlingcaijiDlg* pThis = (CXinlingcaijiDlg*)pObj;
pThis->Start(pThis);
return 0;
} //子线程功能函数
bool CXinlingcaijiDlg::Start(CXinlingcaijiDlg* pObj)
{
myLoop(bFlag);
AfxMessageBox("客户端子线程退出循环");
return TRUE;
} //断开连接
void CXinlingcaijiDlg::OnButton2()
{
//修改Static变量
CXinlingcaijiDlg::bFlag = 0;
if (hThread != NULL)
{
//等待线程正常退出
WaitForSingleObject(hThread,2000);
if (hThread != NULL)
{
CloseHandle(hThread);
}
}
DWORD m;
GetExitCodeThread(hThread,&m);
if ( m == STILL_ACTIVE )
{ //强制关闭线程
TerminateThread(hThread,m);
}
hThread = NULL;
}