局域网聊天软件源代码(包括语音聊天)

本文档提供了一款局域网聊天软件的源代码,包括语音聊天功能。主要涉及C++编程,使用了socket通信,对话框类CChatApp、CChatDlg的实现,以及音频处理类CSound。软件支持服务器和客户端模式,实现了数据的发送和接收,以及语音聊天的录制和播放。
摘要由CSDN通过智能技术生成

 // Chat.h : PROJECT_NAME 应用程序的主头文件
//

#pragma once

#ifndef __AFXWIN_H__
 #error "在包含此文件之前包含“stdafx.h”以生成 PCH 文件"
#endif

#include "resource.h"  // 主符号


// CChatApp:
// 有关此类的实现,请参阅 Chat.cpp
//

class CChatApp : public CWinApp
{
public:
 CChatApp();

// 重写
 public:
 virtual BOOL InitInstance();

// 实现

 DECLARE_MESSAGE_MAP()
};

extern CChatApp theApp;

 

 

 

// Chat.cpp : 定义应用程序的类行为。
//

#include "stdafx.h"
#include "Chat.h"
#include "ChatDlg.h"

//#ifdef _DEBUG
//#define new DEBUG_NEW

 

// CChatApp

BEGIN_MESSAGE_MAP(CChatApp, CWinApp)
 ON_COMMAND(ID_HELP, &CWinApp::OnHelp)
END_MESSAGE_MAP()


// CChatApp 构造

CChatApp::CChatApp()
{
 // TODO: 在此处添加构造代码,
 // 将所有重要的初始化放置在 InitInstance 中
}


// 唯一的一个 CChatApp 对象

CChatApp theApp;


// CChatApp 初始化

BOOL CChatApp::InitInstance()
{
 // 如果一个运行在 Windows XP 上的应用程序清单指定要
 // 使用 ComCtl32.dll 版本 6 或更高版本来启用可视化方式,
 //则需要 InitCommonControlsEx()。否则,将无法创建窗口。
 INITCOMMONCONTROLSEX InitCtrls;
 InitCtrls.dwSize = sizeof(InitCtrls);
 // 将它设置为包括所有要在应用程序中使用的
 // 公共控件类。
 InitCtrls.dwICC = ICC_WIN95_CLASSES;
 InitCommonControlsEx(&InitCtrls);

 CWinApp::InitInstance();

 AfxEnableControlContainer();

 // 标准初始化
 // 如果未使用这些功能并希望减小
 // 最终可执行文件的大小,则应移除下列
 // 不需要的特定初始化例程
 // 更改用于存储设置的注册表项
 // TODO: 应适当修改该字符串,
 // 例如修改为公司或组织名
 SetRegistryKey(_T("应用程序向导生成的本地应用程序"));

 CChatDlg dlg;
 m_pMainWnd = &dlg;
 INT_PTR nResponse = dlg.DoModal();
 if (nResponse == IDOK)
 {
  // TODO: 在此放置处理何时用
  //  “确定”来关闭对话框的代码
 }
 else if (nResponse == IDCANCEL)
 {
  // TODO: 在此放置处理何时用
  //  “取消”来关闭对话框的代码
 }

 // 由于对话框已关闭,所以将返回 FALSE 以便退出应用程序,
 //  而不是启动应用程序的消息泵。
 return FALSE;
}
//#endif

 

// ChatDlg.h : 头文件

#include"Public.h"

 


#include"Server.h"
#include"Client.h"


#ifndef _CChatDlg_h_//用于防止头文件嵌套多次1
#define _CChatDlg_h_//用于防止头文件嵌套多次2

#include"Sound.h"


#pragma once

 

#define WM_DATAREACH WM_APP+110
#define CLIENT 1
#define SERVER 2


// CChatDlg 对话框
class CChatDlg : public CDialog
{
// 构造
public:
 CChatDlg(CWnd* pParent = NULL); // 标准构造函数

// 对话框数据
 enum { IDD = IDD_CHAT_DIALOG };

 protected:
 virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV 支持


// 实现
protected:
 HICON m_hIcon;

 // 生成的消息映射函数
 virtual BOOL OnInitDialog();
 afx_msg void OnSysCommand(UINT nID, LPARAM lParam);
 afx_msg void OnPaint();
 afx_msg HCURSOR OnQueryDragIcon();
 DECLARE_MESSAGE_MAP()

// afx_msg void OnBnClickedButton3();

自定义数据/
public:
 bool ServerFlag;//用于表示是否已经建立了服务器,没有则为false,已经建立则为true
 bool ClientFlag;//用于表示是否已经连接了服务器,没有则为false,已经建立则为true
 CServer Server;//用于服务器端的操作
 CClient Client;//用于服务端的操作
 CSound Sound;//用于音频操作
 CString InPutCString;//用于保存输入窗口的文字数据
 CString AllCString;//用于保存所有聊天记录的文字数据
 int Mark;//用于标识是客户端还是服务器
 bool SoundChat;//用于标识是否已经开始语音聊天,false表示没有,true表示已经建立语音聊天了

    WAVEHDR *p;
自定义消息响应函数-开始/
 LRESULT OnDataReach(WPARAM wParam, LPARAM lParam);//当有新数据到达时执行的代码
 afx_msg LRESULT GetInBufferFull(WPARAM wp, LPARAM lp);//一个buffer满后调用
 afx_msg LRESULT WriteOutBufferEmpty(WPARAM wp, LPARAM lp);//一个buffer播放完后调用
自定义消息响应函数-结束/

 afx_msg void OnBnClickedLinkserver();
 afx_msg void OnBnClickedBuildserver();
 afx_msg void OnIpnFieldchangedIpaddress(NMHDR *pNMHDR, LRESULT *pResult);
 afx_msg void OnBnClickedSend();
 afx_msg void OnEnChangeChat();
 afx_msg void OnBnClickedClose();
 afx_msg void OnBnClickedVoicechat();
};

#endif//用于防止头文件嵌套多次3

 

// ChatDlg.cpp : 实现文件


#include "stdafx.h"
#include "ChatDlg.h"
//#include"Wmiutils.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#endif


// 用于应用程序“关于”菜单项的 CAboutDlg 对话框

class CAboutDlg : public CDialog
{
public:
 CAboutDlg();

// 对话框数据
 enum { IDD = IDD_ABOUTBOX };

 protected:
 virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV 支持

// 实现
protected:
 DECLARE_MESSAGE_MAP()
};

CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
{
}

void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
 CDialog::DoDataExchange(pDX);
}

BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
END_MESSAGE_MAP()


// CChatDlg 对话框

 


CChatDlg::CChatDlg(CWnd* pParent /*=NULL*/)
 : CDialog(CChatDlg::IDD, pParent)
{
 ServerFlag=false;//初始化还没有建立服务器
 ClientFlag=false;
 Mark=0;
 AllCString="";
 SoundChat=false;
 p=(WAVEHDR *)malloc(sizeof(WAVEHDR)+MAX_BUFFER_SIZE);
 m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}

void CChatDlg::DoDataExchange(CDataExchange* pDX)
{
 CDialog::DoDataExchange(pDX);
}

BEGIN_MESSAGE_MAP(CChatDlg, CDialog)
 ON_WM_SYSCOMMAND()
 ON_WM_PAINT()
 ON_WM_QUERYDRAGICON()
 //}}AFX_MSG_MAP
// ON_BN_CLICKED(IDC_BUTTON3, &CChatDlg::OnBnClickedButton3)
ON_BN_CLICKED(IDB_LINKSERVER, &CChatDlg::OnBnClickedLinkserver)
ON_BN_CLICKED(IDB_BUILDSERVER, &CChatDlg::OnBnClickedBuildserver)
ON_NOTIFY(IPN_FIELDCHANGED, IDI_IPADDRESS, &CChatDlg::OnIpnFieldchangedIpaddress)
//ON_WM_CREATE()
ON_BN_CLICKED(IDB_SEND, &CChatDlg::OnBnClickedSend)
用户自定义的消息-开始///
 ON_MESSAGE(WM_DATAREACH,OnDataReach)
 ON_MESSAGE(MM_WIM_DATA,GetInBufferFull)//一个buffer满了后调用
 ON_MESSAGE(MM_WOM_DONE,WriteOutBufferEmpty)//buffer的内容被播放完了后,产生的消息调用这个函数
用户自定义的消息-结束///


//ON_EN_CHANGE(IDE_EDITCHAT, &CChatDlg::OnEnChangeEditchat)
//ON_EN_MAXTEXT(IDE_EDITCHAT, &CChatDlg::OnEnMaxtextEditchat)
//ON_EN_CHANGE(IDE_EDITCHAT, &CChatDlg::OnEnChangeEditchat)
ON_EN_CHANGE(IDE_CHAT, &CChatDlg::OnEnChangeChat)
ON_BN_CLICKED(IDB_CLOSE, &CChatDlg::OnBnClickedClose)
ON_BN_CLICKED(IDB_VOICECHAT, &CChatDlg::OnBnClickedVoicechat)
END_MESSAGE_MAP()


// CChatDlg 消息处理程序

BOOL CChatDlg::OnInitDialog()
{
 CDialog::OnInitDialog();

 // 将“关于...”菜单项添加到系统菜单中。

 // IDM_ABOUTBOX 必须在系统命令范围内。
 ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
 ASSERT(IDM_ABOUTBOX < 0xF000);

 CMenu* pSysMenu = GetSystemMenu(FALSE);
 if (pSysMenu != NULL)
 {
  CString strAboutMenu;
  strAboutMenu.LoadString(IDS_ABOUTBOX);
  if (!strAboutMenu.IsEmpty())
  {
   pSysMenu->AppendMenu(MF_SEPARATOR);
   pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
  }
 }

 // 设置此对话框的图标。当应用程序主窗口不是对话框时,框架将自动
 //  执行此操作
 SetIcon(m_hIcon, TRUE);   // 设置大图标
 SetIcon(m_hIcon, FALSE);  // 设置小图标

 // TODO: 在此添加额外的初始化代码

 return TRUE;  // 除非将焦点设置到控件,否则返回 TRUE
}

void CChatDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
 if ((nID & 0xFFF0) == IDM_ABOUTBOX)
 {
  CAboutDlg dlgAbout;
  dlgAbout.DoModal();
 }
 else
 {
  CDialog::OnSysCommand(nID, lParam);
 }
}

// 如果向对话框添加最小化按钮,则需要下面的代码
//  来绘制该图标。对于使用文档/视图模型的 MFC 应用程序,
//  这将由框架自动完成。

void CChatDlg::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
 {
  CDialog::OnPaint();
 }

 ///程序员添加代码-开始
 ((CIPAddressCtrl *)GetDlgItem(IDI_IPADDRESS))->SetAddress(::htonl(::inet_addr("192.168.177.29")));
 ((CEdit *)this->GetDlgItem(IDE_PORT))->SetWindowTextA("7000");
 ((CButton *)this->GetDlgItem(IDB_SEND))->SetFocus();//将焦点设置为发送按钮
 ///程序员添加代码-结束
}

//当用户拖动最小化窗口时系统调用此函数取得光标
//显示。
HCURSOR CChatDlg::OnQueryDragIcon()
{
 return static_cast<HCURSOR>(m_hIcon);
}


void CChatDlg::OnBnClickedLinkserver()
{
 Client.InitM_dlg(this);
 // TODO: 在此添加控件通知处理程序代码
 if(ClientFlag==false)
 {
  Client.GetServerAddress();
  if(Client.AddSocketLib()&&Client.CreateSocket()&&Client.ConnectSocket())
  {
   ClientFlag=true;
   this->GetDlgItem(IDE_LINKSTATE)->SetWindowText("服务器连接成功");
   Mark=CLIENT;
   ::WSAAsyncSelect(Client.ClientSocket,this->m_hWnd,
    WM_DATAREACH,FD_OOB|FD_READ|FD_WRITE|FD_ACCEPT|FD_CLOSE|FD_CONNECT);
   ::WSAAsyncSelect(Client.ClientSocketSound,this->m_hWnd,
    WM_DATAREACH,FD_OOB|FD_READ|FD_WRITE|FD_ACCEPT|FD_CLOSE|FD_CONNECT);
   return ;
  }
  return ;
 }
 else
   return ;
}

void CChatDlg::OnBnClickedBuildserver()
{
 // TODO: 在此添加控件通知处理程序代码
 Server.InitM_dlg(this);

 if(ServerFlag==false)
 {
  Server.GetServerAddress();
  if(Server.AddSocketLib()&&
   Server.CreateSocket()&&
   Server.BindSocket()&&
   Server.ListeSocket()&&
   Server.AcceptClient())
   {
    ServerFlag=true;
    this->GetDlgItem(IDE_BUILDSTATE)->SetWindowText("服务器设置成功");
    Mark=SERVER;

    ::WSAAsyncSelect(Server.C

一个面向局域网、互联网的即时聊天工具,它专门针对学校及企业内部的网络讯而开发的。 Messenger除了具有一般聊天工具都有的基础功能以外,还有自定义表情符等高级功能,使用简单,服务器无需特别数据库配置。 本软件很适合作为学校、企业内部局域网讯工具。 用户登录基本原理 1.用户登录,客户端根据用户填写的IP向服务器发送连接请求,若IP正确且服务器工作正常。服务器会在Winsock数组(Servicesocket(i))中建立一个连接,同时在自定义类型数组UserInfo(u)中初始化一个索引值与该用户使用的Servicesocket索引(Index属性)值相同的元素,并将其所有值设置为N/A(执行LogIn函数)。然后,服务器调用 New_User 、Login_user 判断用户提交资料与服务器存储的用户资料是否相符(密码是否正确、是否新用户、服务器状况是否允许用户登录等)。若条件符合,服务器向客户端发送登录成功信号(.LoginGood Svc2)并将用户资料写进属于该用户的UserInfo类中。否则向客户端发送登录失败信号(.LoginBad [失败原因代号]),断开连接。 2.用户收到服务器的登录成功信号后,向服务器提交获取好友列表请求(.getbuddys)。服务器收到该请求后调用 GetBuddysFromDB 、Get_User_buddies 完成对该用户好友的数据搜索,并将该用户的所有好友的名称、状态合并为一条命令发送给指定的用户。客户端接收到命令后立刻进行解析,完成对好友的添加及状态更新(利用Wordfunc 模块中的函数)。 3.一个用户登录成功后,服务器会向所有连接在其上的用户(无论该用户处于何种状态)发送一个用户上线状态知。其它用户接受该知后根据情况自动决定是否进行更新。 发送/接收信息基本原理 1.当用户点击“发送”按钮或过其他方式命令客户端发送信息时,客户端将Richtextbox 中的信息代码(TextRTF属性)的开头附加上起始标志(.msg )、在其末尾添加接收用户的名称和结束标志( ||),然后向服务器发送该信息。 2.服务器接收到客户端发出的消息后,根据信息头标志(.msg)判断这是一则聊天信息,同时根据信息结束标志( ||)判断该信息是否完整(若不完整,写入缓冲字符串数组)、获取信息的接收用户。判断完毕后,找到对应用户使用的Servicesocket,向该用户发送信息(若该用户不在线,信息将写入临时文件储存,待该用户上线再发送) ZX Messenger 除文件传送和二人模式外,所有讯均采用这种模式。 3.信息被转发到目标用户后,将再一次进行完整性判断(因为Winsock发送数据包大小受网络情况限制)并对数据进行连接。然后,使用 Word 函数取出有效信息并显示。 Messenger 使用 Microsoft Visual Basic 6.0 开发,(除去各附件)本软件大体分为两个部分——客户端和服务器端(是典型的C/S架构)。其客户端和服务器端依靠Winsock进行讯(使用TCP/IP 协议),服务器过建立Winsock控件数组实现多客户端同时连接的支持。Messenger 的消息走向主要采用 客户端发送——服务器中转——客户端接收的模式(个别功能例外)。 ZX Messenger 适用于 Windows 95/98[注]/Me/2000/XP/.Net Server 2003 [注]:本软件只适用于安装了Microsoft Office或其他带有 Microsoft Visual Basic 6.0 运行库 的 Windows 95/98操作系统,对于没有安装 Microsoft Visual Basic 6.0 运行库的WINDOWS 95/98 ,本软件会无法运行,对于这种情况,请下载 Microsoft Visual Basic 6.0 运行库 并安装。Win98 以后的操作系统不存在此问题。
评论 31
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值