我的大作业——MFC开发的聊天工具(局域网形式,飞秋的半实现版)
来源:互联网 发布:it治理与it管理的区别 编辑:程序博客网 时间:2024/06/04 18:00
///////////////////////////////////////////
// TCPClient.h文件
include
include
include
pragma comment(lib,”WS2_32.lib”)
class CMyApp : public CWinApp
{
public:
BOOL InitInstance();
};
class CMainDialog : public CDialog
{
public:
CMainDialog(CWnd* pParentWnd = NULL);
protected:
// 连接服务器
BOOL Connect(LPCTSTR pszRemoteAddr, u_short nPort);
// 向文本框中添加文本
void AddStringToList(LPCTSTR pszText, BOOL bRecv = TRUE);
protected:
// 状态栏子窗口控件
CStatusBarCtrl m_bar;
CListCtrl m_Ctrl;
// 用于与服务器取得连接的套节字句柄
SOCKET m_socket;
protected:
virtual BOOL OnInitDialog();
virtual void OnCancel();
// 取得或断开连接
afx_msg void OnButtonConnect();
// 发送数据
afx_msg void OnButtonSend();
// 清空编辑框
afx_msg void OnButtonClear();
afx_msg void OnClickItem(NMHDR* pNMHDR, LRESULT* pResult);
// 套节字通知事件
afx_msg long OnSocket(WPARAM wParam, LPARAM lParam);
afx_msg void OnSendFile();afx_msg void Receivefile();DECLARE_MESSAGE_MAP()
};
/////////////////////////////////////////////////
// TCPClient.cpp文件
include “TCPClient.h”
include “resource.h”
// 定义网络事件通知消息s
include “ZMySocket.h”
include “afxdlgs.h”
include
define WM_SOCKET WM_USER + 1
define port 8888
define IDC_LIST 101
CMyApp theApp;
int nRow;
BOOL CMyApp::InitInstance()
{
// 初始化Winsock库
WSADATA wsaData;
WORD sockVersion = MAKEWORD(2, 0);
::WSAStartup(sockVersion, &wsaData);
// 弹出主窗口对话框
CMainDialog dlg;
m_pMainWnd = &dlg;
dlg.DoModal();
// 释放Winsock库
::WSACleanup();
return FALSE;
}
CMainDialog::CMainDialog(CWnd* pParentWnd):CDialog(IDD_MAINDIALOG, pParentWnd)
{
}
BEGIN_MESSAGE_MAP(CMainDialog, CDialog)
ON_BN_CLICKED(IDC_CONNECT, OnButtonConnect)
ON_BN_CLICKED(IDC_SEND, OnButtonSend)
ON_BN_CLICKED(IDC_CLEAR, OnButtonClear)
ON_BN_CLICKED(IDC_SendFile,OnSendFile)
ON_MESSAGE(WM_SOCKET, OnSocket)
END_MESSAGE_MAP()
BOOL CMainDialog::OnInitDialog()
{
CDialog::OnInitDialog();
// 设置图标
SetIcon(theApp.LoadIcon(IDI_MAIN), FALSE);
// 创建状态栏,设置它的属性
m_bar.Create(WS_CHILD | WS_VISIBLE | SBS_SIZEGRIP, CRect(0, 0, 0, 0), this, IDC_LIST);
m_bar.SetBkColor(RGB(0, 0, 0)); // 背景色
int arWidth[] = { 200, -1 };
m_bar.SetParts(2, arWidth); // 分栏
m_bar.SetText(“”, 1, 0); // 第一个栏的文本
m_bar.SetText(” 空闲”, 0, 0); // 第二个栏的文本
// 初始化发送按钮和发送编辑框的状态
//win32代码
m_Ctrl.Create(WS_VISIBLE, CRect(400, 8, 650, 270), this, 101);
//m_Ctrl.SetBkColor(RGB(100, 100, 100));
m_Ctrl.InsertColumn(0, “用户名”,LVCFMT_LEFT, 100);
m_Ctrl.InsertColumn(1, “IP”,LVCFMT_LEFT, 150);
m_Ctrl.SetExtendedStyle(LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES | LVS_EX_HEADERDRAGDROP | LVS_EX_TRACKSELECT);LONG lStyle;lStyle = GetWindowLong(m_Ctrl.m_hWnd, GWL_STYLE);lStyle &= ~LVS_TYPEMASK; //清除显示方式位lStyle |= LVS_REPORT; //设置styleSetWindowLong(m_Ctrl.m_hWnd, GWL_STYLE, lStyle);//设置stylenRow = m_Ctrl.GetItemCount();GetDlgItem(IDC_SEND)->EnableWindow(FALSE);GetDlgItem(IDC_TEXT)->EnableWindow(FALSE);// 初始化连接套节字m_socket = INVALID_SOCKET;return TRUE;
}
void CMainDialog::OnCancel()
{
if(m_socket != INVALID_SOCKET)
::closesocket(m_socket);
CDialog::OnCancel();
}
void CMainDialog::OnButtonClear()
{
GetDlgItem(IDC_INFO)->SetWindowText(“”);
}
void CMainDialog::OnButtonConnect()
{
if(m_socket == INVALID_SOCKET) // 连接服务器
{
// 取得服务器地址
CString sAddr = “10.140.17.21”;
// 试图连接服务器 if(!Connect(sAddr, port)) { MessageBox("连接服务器出错!"); return; } // 设置用户界面 GetDlgItem(IDC_CONNECT)->SetWindowText("取消"); //m_bar.SetText(" 正在连接……", 0, 0);}else // 断开服务器{ // 关闭套节字 ::closesocket(m_socket); m_socket = INVALID_SOCKET; // 设置用户界面 GetDlgItem(IDC_CONNECT)->SetWindowText("连接服务器"); m_bar.SetText(" 空闲", 0, 0); //GetDlgItem(IDC_ADDR)->EnableWindow(TRUE); //GetDlgItem(IDC_PORT)->EnableWindow(TRUE); GetDlgItem(IDC_TEXT)->EnableWindow(FALSE); GetDlgItem(IDC_SEND)->EnableWindow(FALSE); m_Ctrl.DeleteAllItems();}
}
long CMainDialog::OnSocket(WPARAM wParam, LPARAM lParam)
{
// 取得有事件发生的套节字句柄
SOCKET s = wParam;
// 查看是否出错
if(WSAGETSELECTERROR(lParam))
{ if(m_socket != SOCKET_ERROR) OnButtonConnect(); m_bar.SetText(" 连接出错!", 0, 0); return 0;}// 处理发生的事件switch(WSAGETSELECTEVENT(lParam)){ case FD_CONNECT: // 套节字正确的连接到服务器 { // 设置用户界面 GetDlgItem(IDC_CONNECT)->SetWindowText("断开连接"); //GetDlgItem(IDC_ADDR)->EnableWindow(FALSE); //GetDlgItem(IDC_PORT)->EnableWindow(FALSE); GetDlgItem(IDC_TEXT)->EnableWindow(TRUE); GetDlgItem(IDC_SEND)->EnableWindow(TRUE); m_bar.SetText(" 已经连接到服务器", 0, 0); } break;case FD_READ: // 套接字接受到对方发送过来的数据包 { // 从服务器接受数据 char szText[1024] = { 0 }; ::recv(s, szText, 1024, 0); // 显示给用户 AddStringToList(CString(szText) + "\r\n"); } break;case FD_CLOSE: OnButtonConnect(); break;}return 0;
}
void CMainDialog::OnButtonSend()
{
if(m_socket == INVALID_SOCKET)
{
return;
}
// 取得要发送的字符串CString sText;CString str;for (int i = 0; i<m_Ctrl.GetItemCount(); i++){ if (m_Ctrl.GetItemState(i, LVIS_SELECTED) == LVIS_SELECTED) { str.Format("%d", i); sText += str; sText += ","; }}sText += " ";CString sText2;GetDlgItem(IDC_TEXT)->GetWindowText(sText2);sText += sText2;// 添加一个“回车换行”// 注意,添加它并不是必须的,但是如果使用本软件作为客户端调试网络协议,// 比如SMTP、FTP等,就要添加它了。因为这些协议都要求使用“回车换行”作为一个命令的结束标记sText += "\r\n";// 发送数据到服务器SOCKET_STREAM_FILE_INFO StreamFileInfo;memset(&StreamFileInfo, 0, sizeof(SOCKET_STREAM_FILE_INFO));strcpy(StreamFileInfo.text,sText);StreamFileInfo.sendflags = MESSAGE;if (::send(m_socket, (LPSTR)&StreamFileInfo, sizeof(StreamFileInfo), 0) != -1){ sText2 += "\r\n"; AddStringToList(sText2, FALSE); GetDlgItem(IDC_TEXT)->SetWindowText("");}
}
BOOL CMainDialog::Connect(LPCTSTR pszRemoteAddr, u_short nPort)
{
// 创建套节字
m_socket = ::socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if(m_socket == INVALID_SOCKET)
{
return FALSE;
}
// 设置socket为窗口通知消息类型::WSAAsyncSelect(m_socket, m_hWnd, WM_SOCKET, FD_CONNECT | FD_CLOSE | FD_WRITE | FD_READ);// 假定szAddr是IP地址ULONG uAddr = ::inet_addr(pszRemoteAddr); if(uAddr == INADDR_NONE){ // 不是IP地址,就认为这是主机名称 // 从主机名取得IP地址 hostent* pHost = ::gethostbyname(pszRemoteAddr); if(pHost == NULL) { ::closesocket(m_socket); m_socket = INVALID_SOCKET; return FALSE; } // 得到以网络字节顺序排列的IP地址 uAddr = ((struct in_addr*)*(pHost->h_addr_list))->s_addr; } // 填写服务器地址信息sockaddr_in remote; remote.sin_addr.S_un.S_addr = uAddr; remote.sin_family = AF_INET; remote.sin_port = htons(nPort); // 连接到远程机 ::connect(m_socket, (sockaddr*)&remote, sizeof(sockaddr));return TRUE;
}
void CMainDialog::AddStringToList(LPCTSTR pszText, BOOL bRecv)
{
CString strEdit;
GetDlgItem(IDC_INFO)->GetWindowText(strEdit);
if (bRecv){ CString a = CString(pszText); char a1 = a[0]; if (a1 == '1') { m_Ctrl.DeleteAllItems(); int pos = a.Find("\r\n"); CString cs; cs.Format("%d", pos); //strEdit += cs; //strEdit += a; bool assure = true; while (pos != 0) { CString str1 = a.Left(pos); int lenn = a.GetLength() - pos; a = a.Right(lenn - 1); int pos1 = str1.Find(":"); CString left = str1.Left(pos1); int len2; if (assure) len2 = left.GetLength() - 1; else len2 = left.GetLength() - 2; left = left.Right(len2); int len = str1.GetLength() - pos1 - 1; CString right = str1.Right(len); /* strEdit += left; strEdit += "hahah"; strEdit += right; strEdit += "\r\n"; */ m_Ctrl.InsertItem(nRow, ""); m_Ctrl.SetItemText(nRow, 0, left); m_Ctrl.SetItemText(nRow, 1, right); //strEdit += a; pos = a.Find("\r\n"); cs.Format("%d", pos); if (pos == 1) pos--; //strEdit += cs; assure = false; } /* CString str1 = a.Left(pos); int lenn = a.GetLength()-pos; a = a.Right(lenn); int pos1 = str1.Find(":"); CString left = str1.Left(pos1); int len2 = left.GetLength() - 1; left = left.Right(len2); int len = str1.GetLength() - pos1 - 1; CString right = str1.Right(len); strEdit += left; strEdit += "hahah"; strEdit += right; m_Ctrl.InsertItem(nRow, ""); m_Ctrl.SetItemText(nRow, 0, left); m_Ctrl.SetItemText(nRow, 1, right); pos = a.Find("\r\n"); CString cs; cs.Format("%d", pos); strEdit += cs; */ /* CString left = a.Left(pos); int len2 = left.GetLength() - 1; left = left.Right(len2); int len = a.GetLength() - pos - 1; CString right = a.Right(len); strEdit += left; strEdit += "hahah"; strEdit += right; m_Ctrl.InsertItem(nRow, ""); m_Ctrl.SetItemText(nRow, 0, left); m_Ctrl.SetItemText(nRow, 1, right); */ } else { strEdit += "【ReceiveFrom】"; strEdit += a; strEdit += "\r\n"; }}else{ strEdit += "【Send】:"; strEdit += pszText;}GetDlgItem(IDC_INFO)->SetWindowText(strEdit);
}
void CMainDialog::OnSendFile()
{
CFileDialog Dlg(TRUE);if (Dlg.DoModal() != IDOK) return;CFile myFile;if (!myFile.Open(Dlg.GetPathName(), CFile::modeRead | CFile::typeBinary)){ AfxMessageBox("文件不存在!", MB_OK | MB_ICONERROR); return;}/*char name[32];int nGethostname;nGethostname = gethostname(name, sizeof(name));if(nGethostname == SOCKET_ERROR){return ;}//本地struct hostent FAR * hostent;hostent = gethostbyname(name);char * host = inet_ntoa(*((struct in_addr *)hostent->h_addr));*/Message message;::memset(&message, '\0', sizeof(message));message.sendflags = SENDFILE;//::strcpy((LPSTR)(LPCTSTR)message.ipaddress, host);//::strcpy((LPSTR)(LPCTSTR)message.username,ipAddr);/*m_socket.Send(&message, sizeof(message), 0);///////////////////////////////////////////CMySocket fileSocket;//{{socket 初始化bool isFileCreate;isFileCreate = fileSocket.Create();if(isFileCreate == false){::MessageBox(NULL, "创建 socket 失败 !", "Message Box", MB_OK);::WSACleanup();return;}//{{Bindbool bBind;struct sockaddr_in serveraddr;int length;serveraddr.sin_family = AF_INET;serveraddr.sin_port = PORT;serveraddr.sin_addr.s_addr = inet_addr(host);length = sizeof(struct sockaddr_in);bBind = fileSocket.Bind((struct sockaddr *)&serveraddr, length);if(bBind == false){::MessageBox(NULL, "绑定 socket 失败 jksajd!", "Message Box", MB_OK);::WSACleanup();return;}fileSocket.Listen();SOCKET sockRecv;sockRecv = fileSocket.Accept((struct sockaddr FAR*)&serveraddr, &length);*//////////////////////////////////////////////////*CSocket sockSrvr;sockSrvr.Create(800);sockSrvr.Listen();CSocket sockRecv;sockSrvr.Accept(sockRecv);*/SOCKET_STREAM_FILE_INFO StreamFileInfo;WIN32_FIND_DATA FindFileData;FindClose(FindFirstFile(Dlg.GetPathName(), &FindFileData));memset(&StreamFileInfo, 0, sizeof(SOCKET_STREAM_FILE_INFO));strcpy(StreamFileInfo.szFileTitle, myFile.GetFileTitle());StreamFileInfo.dwFileAttributes = FindFileData.dwFileAttributes;StreamFileInfo.ftCreationTime = FindFileData.ftCreationTime;StreamFileInfo.ftLastAccessTime = FindFileData.ftLastAccessTime;StreamFileInfo.ftLastWriteTime = FindFileData.ftLastWriteTime;StreamFileInfo.nFileSizeHigh = FindFileData.nFileSizeHigh;StreamFileInfo.nFileSizeLow = FindFileData.nFileSizeLow;StreamFileInfo.sendflags = SENDFILE;//::send(sockRecv,&(char *)StreamFileInfo,sizeof(SOCKET_STREAM_FILE_INFO),0);UINT dwRead = 0;//while (dwRead<StreamFileInfo.nFileSizeLow)//{ byte* data = new byte[10240]; UINT dw = myFile.Read(data, 10240); //message.fileBuffer = new byte[1024]; for (int i = 0; i < dw; i++) StreamFileInfo.fileBuffer[i] = data[i]; StreamFileInfo.dw = dw; send(m_socket, (LPSTR)&StreamFileInfo, sizeof(SOCKET_STREAM_FILE_INFO), 0); //::send(sockRecv,(char *)data, dw,0); dwRead += dw;//}myFile.Close();//::closesocket(sockRecv);
}
void CMainDialog::Receivefile()
{
AfxMessageBox(“接收完毕!”);
AfxSocketInit(NULL);
CSocket sockClient;
sockClient.Create();
CString szIP;
if (!sockClient.Connect((LPCTSTR)szIP, 800))
{
AfxMessageBox(“连接到对方机器失败!”);
return;
}
SOCKET_STREAM_FILE_INFO StreamFileInfo;sockClient.Receive(&StreamFileInfo, sizeof(SOCKET_STREAM_FILE_INFO));CFile destFile(StreamFileInfo.szFileTitle, CFile::modeCreate | CFile::modeWrite | CFile::typeBinary);UINT dwRead = 0;while (dwRead<StreamFileInfo.nFileSizeLow){ byte* data = new byte[1024]; memset(data, 0, 1024); UINT dw = sockClient.Receive(data, 1024); destFile.Write(data, dw); dwRead += dw;}SetFileTime((HANDLE)destFile.m_hFile, &StreamFileInfo.ftCreationTime, &StreamFileInfo.ftLastAccessTime, &StreamFileInfo.ftLastWriteTime);destFile.Close();SetFileAttributes(StreamFileInfo.szFileTitle, StreamFileInfo.dwFileAttributes);::closesocket(sockClient);AfxMessageBox("接收完毕!");
}
Server实现///////////////////////////////////////////// TCPServer.h文件#include <afxwin.h> // 10TCPServer #include <afxcmn.h>#include <winsock2.h> // 告诉连接器与WS2_32库连接#pragma comment(lib,"WS2_32.lib")#define MAX_SOCKET 56 // 定义此服务器所能接受的最大客户量class CMyApp : public CWinApp{public: BOOL InitInstance();};class CMainDialog : public CDialog{public: CMainDialog(CWnd* pParentWnd = NULL);protected: // 创建套节字,并设置为监听状态,准备接受客户的连接 BOOL CreateAndListen(int nPort); // 关闭所有套节字,包括监听套节字和所有accept函数返回的套节字 void CloseAllSocket(); // 向客户连接列表中添加一个客户 BOOL AddClient(SOCKET s, CString list2); // 从客户连接列表中移处一个客户 void RemoveClient(SOCKET s);protected: // 两个子窗口控件,一个是状态栏,一个是列表框 CStatusBarCtrl m_bar; CListBox m_listInfo; // 监听套节字句柄 SOCKET m_socket; CString clients[MAX_SOCKET]; // 客户连接列表 SOCKET m_arClient[MAX_SOCKET]; // 套节字数组 int m_nClient; // 上述数组的大小protected: virtual BOOL OnInitDialog(); virtual void OnCancel(); // 开启或停止服务 afx_msg void OnStart(); // 清空信息 afx_msg void OnClear(); // 套节字通知事件 afx_msg long OnSocket(WPARAM wParam, LPARAM lParam); //发送文件 afx_msg void OnSendFile(); DECLARE_MESSAGE_MAP()};
/////////////////////////////////////////////////////
// TCPServer.cpp文件
include “TCPClient.h”
include “resource.h”
include “ZMySocket.h”
include
include “afxdlgs.h”
include
define WM_SOCKET WM_USER + 1
typedef enum
{
USERNAME = 10,
MESSAGE = 20,
QUIT = 30,
SENDFILE = 40,
BURR = 60
}SendFlags;
typedef struct _SOCKET_STREAM_FILE_INFO {
SendFlags sendflags;TCHAR szFileTitle[128]; //文件的标题名DWORD dwFileAttributes; //文件的属性FILETIME ftCreationTime; //文件的创建时间FILETIME ftLastAccessTime; //文件的最后访问时间FILETIME ftLastWriteTime; //文件的最后修改时间DWORD nFileSizeHigh; //文件大小的高位双字DWORD nFileSizeLow; //文件大小的低位双字DWORD dwReserved0; //保留,为0DWORD dwReserved1; //保留,为0UINT dw;char text[1024];byte fileBuffer[10240];
} SOCKET_STREAM_FILE_INFO, *PSOCKET_STREAM_FILE_INFO;
typedef struct
{
SendFlags sendflags;
char username[64];
char ipaddress[64];
char buffer[1024];
UINT dw;
byte fileBuffer[1024];
}Message;
/////////////////////////////////////////////
CString str;
CFile* destFile;
UINT dwRead = 0;
TCHAR szFileTitle1[128]; //文件的标题名
DWORD dwFileAttributes1; //文件的属性
FILETIME ftCreationTime1; //文件的创建时间
FILETIME ftLastAccessTime1; //文件的最后访问时间
FILETIME ftLastWriteTime1; //文件的最后修改时间
DWORD nFileSizeHigh1; //文件大小的高位双字
DWORD nFileSizeLow1; //文件大小的低位双字
////////////////////////////////////////////
CMyApp theApp;
BOOL CMyApp::InitInstance()
{
// 初始化Winsock库
WSADATA wsaData;WORD sockVersion = MAKEWORD(2, 0);::WSAStartup(sockVersion, &wsaData);// 弹出主窗口对话框CMainDialog dlg;m_pMainWnd = &dlg;dlg.DoModal();// 释放Winsock库::WSACleanup();return FALSE;
}
CMainDialog::CMainDialog(CWnd* pParentWnd):CDialog(IDD_MAINDIALOG, pParentWnd)
{
}
BEGIN_MESSAGE_MAP(CMainDialog, CDialog)
ON_BN_CLICKED(IDC_START, OnStart)
ON_BN_CLICKED(IDC_CLEAR, OnClear)
ON_MESSAGE(WM_SOCKET, OnSocket)
END_MESSAGE_MAP()
BOOL CMainDialog::OnInitDialog()
{
CDialog::OnInitDialog();
// 设置图标
SetIcon(theApp.LoadIcon(IDI_MAIN), FALSE);
// 创建状态栏,设置它的属性
m_bar.Create(WS_CHILD|WS_VISIBLE|SBS_SIZEGRIP, CRect(0, 0, 0, 0), this, 101);
m_bar.SetBkColor(RGB(0xa6, 0xca, 0xf0)); // 背景色
int arWidth[] = { 200, -1 };
m_bar.SetParts(2, arWidth); // 分栏
m_bar.SetText(“”, 1, 0); // 第一个栏的文本
m_bar.SetText(” 空闲”, 0, 0); // 第二个栏的文本
// 设置列表框控件到m_listInfo对象的关联
m_listInfo.SubclassDlgItem(IDC_INFO, this);
// 初始化监听套节字和连接列表m_socket = INVALID_SOCKET;m_nClient = 0; // 下面是取得本地IP地址的过程,将它显示在状态栏的第一个分栏中// 取得本机名称 char szHost[256];::gethostname(szHost, 256);// 通过本机名称取得地址信息HOSTENT* pHost = gethostbyname(szHost);if(pHost != NULL){ CString sIP; // 得到第一个IP地址 in_addr *addr =(in_addr*) *(pHost->h_addr_list); // 显示给用户 sIP.Format(" 本机IP:%s", inet_ntoa(addr[0])); m_bar.SetText(sIP, 0, 0);}return TRUE;
}
void CMainDialog::OnStart()
{
if(m_socket == INVALID_SOCKET) // 开启服务
{
// 取得端口号
CString sPort;
GetDlgItem(IDC_PORT)->GetWindowText(sPort);
int nPort = atoi(sPort);
if(nPort < 1 || nPort > 65535)
{
MessageBox(“端口号错误!”);
return;
}
// 创建监听套节字,使它进入监听状态 if(!CreateAndListen(nPort)) { MessageBox("启动服务出错!"); return; } // 设置相关子窗口控件状态 GetDlgItem(IDC_START)->SetWindowText("停止服务"); m_bar.SetText(" 正在监听……", 0, 0); GetDlgItem(IDC_PORT)->EnableWindow(FALSE);}else // 停止服务{ // 关闭所有连接 CloseAllSocket(); // 设置相关子窗口控件状态 GetDlgItem(IDC_START)->SetWindowText("开启服务"); m_bar.SetText(" 空闲", 0, 0); GetDlgItem(IDC_PORT)->EnableWindow(TRUE);}
}
void CMainDialog::OnCancel()
{
CloseAllSocket();
CDialog::OnCancel();
}
void CMainDialog::OnClear()
{
m_listInfo.ResetContent();
}
long CMainDialog::OnSocket(WPARAM wParam, LPARAM lParam)
{
// 取得有事件发生的套节字句柄
SOCKET s = wParam;
// 查看是否出错
if(WSAGETSELECTERROR(lParam))
{
RemoveClient(s);
::closesocket(s);
return 0;
}
// 处理发生的事件
switch(WSAGETSELECTEVENT(lParam))
{
case FD_ACCEPT: // 监听中的套接字检测到有连接进入
{
if(m_nClient < MAX_SOCKET)
{
sockaddr_in remoteAddr;
int nAddrLen = sizeof(remoteAddr);
// 接受连接请求,新的套节字client是新连接的套节字
SOCKET client = ::accept(s, (SOCKADDR*)&remoteAddr, &nAddrLen);
// 设置新的套节字为窗口通知消息类型
int i = ::WSAAsyncSelect(client,
m_hWnd, WM_SOCKET, FD_READ|FD_WRITE|FD_CLOSE);
CString list = inet_ntoa(remoteAddr.sin_addr); DWORD dwIP = ::inet_addr(list); // 获取主机名称,注意其中第一个参数的转化 hostent* pHost = ::gethostbyaddr((LPSTR)&dwIP, 4, AF_INET); char szHostName[256]; strncpy(szHostName, pHost->h_name, 256); CString list2 ="1" + CString(szHostName) + ":" + list+"\r\n"; AddClient(client,list2); for (i = 0; i < m_nClient; i++) { for (int j = 0; j < m_nClient;j++) ::send(m_arClient[i], clients[j], clients[j].GetLength(), 0); } } else { MessageBox("连接客户太多!"); } } break;case FD_CLOSE: // 检测到套接字对应的连接被关闭。 { RemoveClient(s); ::closesocket(s); for (int i = 0; i < m_nClient; i++) { for (int j = 0; j < m_nClient; j++) ::send(m_arClient[i], clients[j], clients[j].GetLength(), 0); } } break;case FD_READ: // 套接字接受到对方发送过来的数据包 { int nReceive; Message message; // 取得对方的IP地址和端口号(使用getpeername函数) // Peer对方的地址信息 sockaddr_in sockAddr; memset(&sockAddr, 0, sizeof(sockAddr)); int nSockAddrLen = sizeof(sockAddr); ::getpeername(s, (SOCKADDR*)&sockAddr, &nSockAddrLen); // 转化为主机字节顺序 int nPeerPort = ::ntohs(sockAddr.sin_port); // 转化为字符串IP CString sPeerIP = ::inet_ntoa(sockAddr.sin_addr); // 取得对方的主机名称 // 取得网络字节顺序的IP值 DWORD dwIP = ::inet_addr(sPeerIP); // 获取主机名称,注意其中第一个参数的转化 hostent* pHost = ::gethostbyaddr((LPSTR)&dwIP, 4, AF_INET); char szHostName[256]; strncpy(szHostName, pHost->h_name, 256); SOCKET_STREAM_FILE_INFO StreamFileInfo; ::memset(&StreamFileInfo, '\0', sizeof(StreamFileInfo)); //socket的消息放入message中 if (::recv(s, (LPSTR)&StreamFileInfo, sizeof(StreamFileInfo), 0) != 0) { CString fromIp = sPeerIP; if (StreamFileInfo.sendflags == SENDFILE) { CFile destFile2(StreamFileInfo.szFileTitle, CFile::modeCreate | CFile::modeWrite | CFile::typeBinary); ftCreationTime1 = StreamFileInfo.ftCreationTime; ftLastAccessTime1 = StreamFileInfo.ftLastAccessTime; ftLastWriteTime1 = StreamFileInfo.ftLastWriteTime; strcpy(szFileTitle1, StreamFileInfo.szFileTitle); dwFileAttributes1 = StreamFileInfo.dwFileAttributes; nFileSizeLow1 = StreamFileInfo.nFileSizeLow; destFile2.Write(StreamFileInfo.fileBuffer, StreamFileInfo.dw); /* while (dwRead<StreamFileInfo.nFileSizeLow) { ::memset(&message, '\0', sizeof(message)); recv(s,(LPSTR)&message, sizeof(message), 0); destFile.Write(message.fileBuffer, message.dw); dwRead += message.dw; } AfxMessageBox("不懂"); SetFileTime((HANDLE)destFile.m_hFile, &StreamFileInfo.ftCreationTime, &StreamFileInfo.ftLastAccessTime, &StreamFileInfo.ftLastWriteTime); destFile.Close(); SetFileAttributes(StreamFileInfo.szFileTitle, StreamFileInfo.dwFileAttributes); CString a = " 接收到来自IP:" + fromIp + "的文件:" + (CString)StreamFileInfo.szFileTitle; AfxMessageBox(a); */ SetFileTime((HANDLE)destFile2.m_hFile, &StreamFileInfo.ftCreationTime, &StreamFileInfo.ftLastAccessTime, &StreamFileInfo.ftLastWriteTime); destFile2.Close(); SetFileAttributes(StreamFileInfo.szFileTitle, StreamFileInfo.dwFileAttributes); CString a = " 接收到来自IP:" + fromIp + "的文件:" + (CString)StreamFileInfo.szFileTitle; AfxMessageBox(a); } else if (StreamFileInfo.sendflags == MESSAGE) { char szText[1024] = { 0 }; for (int i = 0; i < 1024; i++) { szText[i] = StreamFileInfo.text[i]; } //strcpy(szText, StreamFileInfo.text); CString szText2 = (CString)szText; int pos = szText2.Find(' '); CString left = szText2.Left(pos); int len = szText2.GetLength() - pos; len--; CString szText3 = szText2.Right(len); // 显示给用户 CString strItem = CString(szHostName) + "[" + sPeerIP + "]: " + CString(szText3); //////////////////////OK int i; pos = left.Find(','); CString list; while (pos > 0) { list = left.Left(pos); len = left.GetLength() - pos; len--; left = left.Right(len); pos = left.Find(','); i = atoi((LPCTSTR)list); i = m_nClient - 1 - i; ::send(m_arClient[i], strItem, strItem.GetLength(), 0); } m_listInfo.InsertString(0, strItem); } } else { AfxMessageBox("连接失败"); } /////////////////////////////////////// /* // 取得对方的IP地址和端口号(使用getpeername函数) // Peer对方的地址信息 sockaddr_in sockAddr; memset(&sockAddr, 0, sizeof(sockAddr)); int nSockAddrLen = sizeof(sockAddr); ::getpeername(s, (SOCKADDR*)&sockAddr, &nSockAddrLen); // 转化为主机字节顺序 int nPeerPort = ::ntohs(sockAddr.sin_port); // 转化为字符串IP CString sPeerIP = ::inet_ntoa(sockAddr.sin_addr); // 取得对方的主机名称 // 取得网络字节顺序的IP值 DWORD dwIP = ::inet_addr(sPeerIP); // 获取主机名称,注意其中第一个参数的转化 hostent* pHost = ::gethostbyaddr((LPSTR)&dwIP, 4, AF_INET); char szHostName[256]; strncpy(szHostName, pHost->h_name, 256); // 接受真正的网络数据 char szText[1024] = { 0 }; ::recv(s, szText, 1024, 0); if (szText[0] == '9'&&szText[1] == '9') { } else { CString szText2 = (CString)szText; int pos = szText2.Find(' '); CString left = szText2.Left(pos); int len = szText2.GetLength() - pos; len--; CString szText3 = szText2.Right(len); // 显示给用户 CString strItem = CString(szHostName) + "[" + sPeerIP + "]: " + CString(szText3); //////////////////////OK int i; pos = left.Find(','); CString list; while (pos > 0) { list = left.Left(pos); len = left.GetLength() - pos; len--; left = left.Right(len); pos = left.Find(','); i = atoi((LPCTSTR)list); i = m_nClient - 1 - i; ::send(m_arClient[i], strItem, strItem.GetLength(), 0); } m_listInfo.InsertString(0, strItem); } */ } break;}return 0;
}
BOOL CMainDialog::CreateAndListen(int nPort)
{
if(m_socket == INVALID_SOCKET)
::closesocket(m_socket);
// 创建套节字m_socket = ::socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);if(m_socket == INVALID_SOCKET) return FALSE;// 填写要关联的本地地址sockaddr_in sin;sin.sin_family = AF_INET;sin.sin_port = htons(nPort);sin.sin_addr.s_addr = INADDR_ANY;// 绑定端口if(::bind(m_socket, (sockaddr*)&sin, sizeof(sin)) == SOCKET_ERROR){ return FALSE;}// 设置socket为窗口通知消息类型::WSAAsyncSelect(m_socket, m_hWnd, WM_SOCKET, FD_ACCEPT|FD_CLOSE);// 进入监听模式::listen(m_socket, 5);return TRUE;
}
BOOL CMainDialog::AddClient(SOCKET s, CString list2)
{
if(m_nClient < MAX_SOCKET)
{
// 添加新的成员
m_arClient[m_nClient] = s;
clients[m_nClient++] = list2;
return TRUE;
}
return FALSE;
}
void CMainDialog::RemoveClient(SOCKET s)
{
BOOL bFind = FALSE;
int i;
for(i=0; i
- 我的大作业——MFC开发的聊天工具(局域网形式,飞秋的半实现版)
- 实现局域网语音聊天工具的雏形方案
- 好用的局域网聊天工具
- 聊天工具的开发(1)
- 网络聊天工具的实现
- 免费软件推荐:免费的局域网聊天工具!
- 基于UDP协议的局域网网络聊天工具
- 基于UDP广播的局域网聊天工具
- 我的数据库大作业——学生选课系统实现(准备)
- 嵌入式开发38,39,40天(项目3:基于A8开发板的局域网聊天工具)
- 基于JAVA的聊天工具开发
- MFC做的基于socket聊天工具
- 基于java的socket功能编写的一个局域网聊天工具
- 告别MFC——对大一大作业的汇总——MFC学习
- UDP协议+C#写的一款局域网聊天工具+源代码
- 一个不错的局域网聊天工具之飞鸽传书下载地址
- 采用DWR推送技术+消息队列的局域网聊天工具
- 局域网聊天工具-飞秋(FeiQ)的安装与使用
- java web笔记之Filter防盗链
- PHP获得文件列表
- 单例模式
- @select延伸
- NFS启动根文件系统,遇到Root-NFS: Unable to get mountd port number from server, using default问题
- 我的大作业——MFC开发的聊天工具(局域网形式,飞秋的半实现版)
- 我的android新手杂记
- IOS基础:retain,copy,assign及autorelease
- 分享一些免费的接口
- sql学习(-)
- 分布式数据包抓取系统
- SublimeText3解决中文乱码
- unicode转成UTF8
- java语言IO之FileInput