📄 wbqqchat.cpp
字号:
// wbQQChat.cpp : Defines the class behaviors for the application.
//
#include "stdafx.h"
#include "wbQQChat.h"
#include <afxmt.h> //CMutex
#include <afxtempl.h> //CList
#define PORT (u_short)1976
#define MAXBUFLEN 5025
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
struct socketInfo //利用此结构为每一客户端建立一项,连成链表
{
SOCKET socClient;
u_long client_addr;
CString strUserName;
CWinThread *thread;
};
struct sendInfo //存贮转发信息
{
CString data;
CWinThread *thread;
};
CMutex m_mutex;
sendInfo infoData;
CList<socketInfo, socketInfo&> sockInfoList;
/////////////////////////关闭套接字全局函数/////////////////////////////////////
void closeSocketLink(void *s)
{
SOCKET clientSocket = (SOCKET)s;
int status = shutdown(clientSocket, 2);
int i = WSAGetLastError();
TRACE("WSAGetLastError ()=%d\n", i);
if (status == SOCKET_ERROR)
{
AfxMessageBox("ERROR: shutdown unsuccessful!", MB_OK);
}
status = closesocket(clientSocket);
i = WSAGetLastError();
TRACE("WSAGetLastError ()=%d\n", i);
if (status == SOCKET_ERROR)
{
AfxMessageBox("ERROR: closesocket unsuccessful!", MB_OK);
}
}
////////////////////////////发送消息线程/////////////////////////////////////////
UINT SendData(void *cs)
{
int numsnt;
SOCKET clientSocket = (SOCKET)cs;
CWinThread *now;
while (1)
{
if (infoData.data != "Close!")
{
m_mutex.Lock();
numsnt = send(clientSocket, infoData.data, infoData.data.GetLength(), 0);
if (numsnt == SOCKET_ERROR || numsnt == 0)
{
AfxMessageBox("传输失败!" + GetLastError(), MB_OK);
break;
}
now = infoData.thread;
m_mutex.Unlock();
now->SuspendThread();
}
else
{
closeSocketLink((LPVOID)clientSocket);
break;
}
}
AfxEndThread(0, true);
return 1;
}
////////////////////////////发送消息线程//////////////////////////////////////
UINT RecvData(void *cs)
{
char buffer[MAXBUFLEN];
int numrcv;
SOCKET clientSocket = (SOCKET)cs;
while (1)
{
numrcv = recv(clientSocket, buffer, MAXBUFLEN, 0);
if (numrcv == SOCKET_ERROR || numrcv == 0)
{
AfxMessageBox("连接中断!" + GetLastError(), MB_OK);
break;
}
buffer[numrcv] = '\0';
TRACE("收到信息:%s\n", buffer);
if (strcmp(buffer, "Close!") != 0)
{
char userName[20];
char *pos = strchr(buffer, ':');
int lenBuf = strlen(buffer);
int len = lenBuf - strlen(pos);
pos++;
for (int i=0; i<len; i++)
{
userName[i] = buffer[i];
}
userName[len] = '\0';
POSITION posit = sockInfoList.GetHeadPosition();
socketInfo si;
int count = sockInfoList.GetCount();
for (i=0; i<count; i++)
{
if (posit != NULL)
{
si = sockInfoList.GetNext(posit);
if (si.strUserName.Compare(userName) == 0)
{
m_mutex.Lock();
infoData.data = pos;
infoData.thread = si.thread;
m_mutex.Unlock();
si.thread->ResumeThread();
break;
}
}
if (posit == NULL)
{
CString str = pos;
str += "\n";
str += userName;
str += "现在不在线,请以后再发消息!";
TRACE("用户%s不在线", userName);
send(clientSocket, str, str.GetLength(), 0);
}
}
} //if (strcmp(buffer, "Close!") != 0)
else
{
POSITION posit = sockInfoList.GetHeadPosition();
POSITION postemp;
socketInfo si;
int count = sockInfoList.GetCount();
for (int i=0; i<count; i++)
{
if (posit != NULL)
{
postemp = posit;
si = sockInfoList.GetNext(posit);
if (clientSocket == si.socClient)
{
m_mutex.Lock();
infoData.data = buffer;
m_mutex.Unlock();
si.thread->ResumeThread();
sockInfoList.RemoveAt(postemp);
break;
}
}
}
break;
}
} //while (1)
AfxEndThread(0, true);
return 1;
}
//////////////////////////////////////////////////////////////////////////////
// CWbQQChatApp
BEGIN_MESSAGE_MAP(CWbQQChatApp, CWinApp)
//{{AFX_MSG_MAP(CWbQQChatApp)
// NOTE - the ClassWizard will add and remove mapping macros here.
// DO NOT EDIT what you see in these blocks of generated code!
//}}AFX_MSG
ON_COMMAND(ID_HELP, CWinApp::OnHelp)
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CWbQQChatApp construction
CWbQQChatApp::CWbQQChatApp()
{
// TODO: add construction code here,
// Place all significant initialization in InitInstance
}
/////////////////////////////////////////////////////////////////////////////
// The one and only CWbQQChatApp object
CWbQQChatApp theApp;
/////////////////////////////////////////////////////////////////////////////
// CWbQQChatApp initialization
BOOL CWbQQChatApp::InitInstance()
{
if (!AfxSocketInit())
{
AfxMessageBox(IDP_SOCKETS_INIT_FAILED);
return FALSE;
}
// AfxEnableControlContainer();
// Standard initialization
// If you are not using these features and wish to reduce the size
// of your final executable, you should remove from the following
// the specific initialization routines you do not need.
#ifdef _AFXDLL
Enable3dControls(); // Call this when using MFC in a shared DLL
#else
Enable3dControlsStatic(); // Call this when linking to MFC statically
#endif
if (InitNet(PORT) == false)
return false;
Chat(serverSocket);
return FALSE;
}
bool CWbQQChatApp::InitNet(u_short iPort) //初始化网络,绑定端口,侦听
{
status = WSAStartup(MAKEWORD(1, 1), &Data);
if (status != 0)
{
AfxMessageBox("ERROR: WSAStartup unsuccsessful!", MB_OK);
return false;
}
memset(&serverSockAddr, 0, sizeof (serverSockAddr));
serverSockAddr.sin_port = htons(iPort);
serverSockAddr.sin_family = AF_INET;
serverSockAddr.sin_addr.s_addr = htons(INADDR_ANY);
serverSocket = socket(AF_INET, SOCK_STREAM, 0);
if (serverSocket == INVALID_SOCKET)
{
AfxMessageBox("socket unsuccsessful!" + GetLastError(), MB_OK);
status = WSACleanup();
if (status == SOCKET_ERROR)
{
AfxMessageBox("ERROR: WSACleanup unsuccsessful!" + GetLastError(), MB_OK);
return false;
}
return false;
}
status = bind(serverSocket, (LPSOCKADDR)&serverSockAddr, sizeof (serverSockAddr));
if (status == SOCKET_ERROR)
{
AfxMessageBox("ERROR: bind unsuccsessful!" + GetLastError(), MB_OK);
return false;
}
status = listen(serverSocket, 5);
if (status == SOCKET_ERROR)
{
AfxMessageBox("ERROR: listen unsuccsessful!" + GetLastError(), MB_OK);
return false;
}
return true;
}
void CWbQQChatApp::Chat(SOCKET s)
{
SOCKET clientSocket;
SOCKADDR_IN clientSockAddr;
int status;
int addrLen = sizeof (SOCKADDR_IN);
char buffer[MAXBUFLEN];
int numrcv;
while (1)
{
CWinThread *hHandleSend;
CWinThread *hHandleRecv;
clientSocket = accept(s, (LPSOCKADDR)&clientSockAddr, &addrLen);
numrcv = recv(clientSocket, buffer, MAXBUFLEN, 0);
buffer[numrcv] = '\0';
// DWORD dwThreadId; // returns the thread identifier
hHandleSend = AfxBeginThread(SendData, (LPVOID)clientSocket, 0, 0,
CREATE_SUSPENDED, NULL);
socketInfo info;
info.socClient = clientSocket;
info.strUserName = buffer;
info.thread = hHandleSend;
sockInfoList.AddTail(info);
hHandleRecv = AfxBeginThread(RecvData, (LPVOID)clientSocket);
if (hHandleSend == NULL || hHandleRecv == NULL)
{
AfxMessageBox("ERROR: Unable to create thread!", MB_OK);
status = closesocket(clientSocket);
if (status == SOCKET_ERROR)
{
AfxMessageBox("ERROR: closesocket unsuccessful!", MB_OK);
}
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -