局域网聊天软件源代码(包括语音聊天)
// 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.ConnectSocket,this->m_hWnd,
WM_DATAREACH,FD_OOB|FD_READ|FD_WRITE|FD_ACCEPT|FD_CLOSE|FD_CONNECT);
::WSAAsyncSelect(Server.ConnectSocketSound,this->m_hWnd,
WM_DATAREACH,FD_OOB|FD_READ|FD_WRITE|FD_ACCEPT|FD_CLOSE|FD_CONNECT);
return ;
}
return ;
}
else
return ;
}
void CChatDlg::OnIpnFieldchangedIpaddress(NMHDR *pNMHDR, LRESULT *pResult)
{
LPNMIPADDRESS pIPAddr = reinterpret_cast<LPNMIPADDRESS>(pNMHDR);
// TODO: 在此添加控件通知处理程序代码
*pResult = 0;
}
void CChatDlg::OnBnClickedSend()
{
// TODO: 在此添加控件通知处理程序代码
(this->GetDlgItem(IDE_EDITCHAT))->GetWindowTextA(InPutCString);//把聊天输入窗口里面的文字保存到InPutCString中
if(InPutCString.GetLength()!=0)
{
(this->GetDlgItem(IDE_EDITCHAT))->SetWindowTextA("");
if(Mark==SERVER)
{
AllCString=AllCString+" 服务器:"+InPutCString+"/r/n";
this->GetDlgItem(IDE_CHAT)->SetWindowText(AllCString);
Server.GetSendBuf(InPutCString);
Server.SendData(NULL);
}
else if(Mark==CLIENT)
{
AllCString=AllCString+" 客户端:"+InPutCString+"/r/n";
this->GetDlgItem(IDE_CHAT)->SetWindowText(AllCString);
Client.GetSendBuf(InPutCString);
Client.SendData(NULL);
}
}
}
用户定义消息响应函数-开始///
///
// OnDataReach-开始 //
// 当有新数据到达时执行的代码 //
//
LRESULT CChatDlg::OnDataReach(WPARAM wParam, LPARAM lParam)
{
DWORD MessageLowWord,MessageHignWord;
MessageHignWord=HIWORD(lParam);
MessageLowWord=LOWORD(lParam);
if(wParam==Server.ConnectSocket)//是由Server.ConnectSocket发送来的消息
{
if(MessageLowWord&FD_READ)
{
Server.ReceiveData(NULL);
Server.GetReceiveBuf(this->AllCString);
this->GetDlgItem(IDE_CHAT)->SetWindowText(AllCString);
}
}
else if(wParam==Client.ClientSocket)//是由Client.ClientSocket发送来的消息
{
if(MessageLowWord&FD_READ)
{
Client.ReceiveData(NULL);
Client.GetReceiveBuf(this->AllCString);
this->GetDlgItem(IDE_CHAT)->SetWindowText(AllCString);
}
}
else if(wParam==Server.ConnectSocketSound)//由Server.ConnectSocketSound发送来的消息
{
if(MessageLowWord&FD_READ)
{
Server.ReceiveData(p);
p->lpData=(LPSTR)(p+1);
Sound.Play(p);
}
}
else if(wParam==Client.ClientSocketSound)//由Client.ClientSocketSound发送来的消息
{
if(MessageLowWord&FD_READ)
{
Client.ReceiveData(p);
p->lpData=(LPSTR)(p+1);
Sound.Play(p);
}
}
return 0;
}
///
// OnDataReach-结束 //
// 当有新数据到达时执行的代码 //
//
///
// GetInBufferFull-开始 //
// 一个buffer满后调用 //
//
LRESULT CChatDlg::GetInBufferFull(WPARAM wp, LPARAM lp)
{
if(Sound.FreeRecordBuffer((WAVEHDR *)lp)==false)//脱离输入设备和内存之间的联系
{
::AfxMessageBox("Error in function Sound.FreeRecordBuffer!");
return 0;
}
if(Mark==SERVER)//判断本端是不是服务端
{
Server.SendData((WAVEHDR *)lp);
}
else if(Mark==CLIENT)//判断本段是不是客户端
{
Client.SendData((WAVEHDR *)lp);
}
else return 0;//如果还没有建立连接
// Sound.Play((WAVEHDR*)lp);//在本地播放出声音
Sound.AddRecordBuffer((WAVEHDR *)lp);
return 0;
}
///
// GetInBufferFull-结束 //
// 一个buffer满后调用 //
//
///
// WriteOutBufferEmpty-开始 //
// 一个buffer播放完后调用 //
//
LRESULT CChatDlg::WriteOutBufferEmpty(WPARAM wp, LPARAM lp)
{
for(int i=0;i<BUFNUM;i++)
{
if((WAVEHDR *)lp==Sound.m_bufferOut[i])//判断是哪个buffer已经播放完了
{
Sound.FreePlayBuffer(Sound.m_bufferOut[i]);//释放m_bufferOut[i]和输出设备之间的联系
Sound.m_Outusingflag[i]=false;//标识m_bufferOut[i]还没有和输出设备联系起来
break;
}
}
return 0;
}
///
// WriteOutBufferEmpty-结束 //
// 一个buffer播放完后调用 //
//
用户定义消息响应函数-结束///
void CChatDlg::OnEnChangeChat()
{
// TODO: 如果该控件是 RICHEDIT 控件,则它将不会
// 发送该通知,除非重写 CDialog::OnInitDialog()
// 函数并调用 CRichEditCtrl().SetEventMask(),
// 同时将 ENM_CHANGE 标志“或”运算到掩码中。
// TODO: 在此添加控件通知处理程序代码
// (CEdit *)(this->GetDlgItem(IDE_CHAT))->
}
void CChatDlg::OnBnClickedClose()
{
// TODO: 在此添加控件通知处理程序代码
this->DestroyWindow();
}
void CChatDlg::OnBnClickedVoicechat()
{
// TODO: 在此添加控件通知处理程序代码
if(!SoundChat)
{
if(ServerFlag==true||ClientFlag==true)
{
if(!Sound.Init(this))//初始化音频设备
{
::AfxMessageBox("初始化音频设备失败!");
return ;
}
Sound.Record();//开始录音
SoundChat=true;
this->SetDlgItemTextA(IDB_VOICECHAT,"停止语音");
}
else
{
::AfxMessageBox("还没有建立连接!");
return ;
}
}// if(!SoundChat)
else
{
Sound.StopRecord();
SoundChat=false;
this->SetDlgItemTextA(IDB_VOICECHAT,"语音聊天");
}
}
#pragma once
#define BUFSIZE 1000
#include"Public.h"
class CChatDlg;
class CClient
{
public:
//用于语音聊天定义-开始///
SOCKET ClientSocket;
struct sockaddr_in ServerAddress;//服务器的ip地址以及端口号
struct sockaddr_in ClientAddress;//客户端的ip地址以及端口号
char SendBuf[BUFSIZE];//发送缓存大小
char ReceiveBuf[BUFSIZE];//接收缓存大小
//用于语音聊天定义-结束///
//用于语音聊天定义-开始///
SOCKET ClientSocketSound;//用于客户端的音频聊天的套接字
struct sockaddr_in ServerAddSound;//用于进行音频聊天的服务器的ip地址以及端口号
struct sockaddr_in ClientAddSound;//用于进行音频聊天的客户端的ip地址以及端口号
//用于语音聊天定义-结束///
CChatDlg *m_dlg;
public:
CClient(void);
~CClient(void);
bool AddSocketLib();//加载套接字库
bool CreateSocket();//创建监听套接字
bool ConnectSocket();//连接到服务器
bool SendData(WAVEHDR* p);//向客户端发送数据
bool ReceiveData(WAVEHDR* p);//接收客户端发来的数据
bool InitM_dlg(CChatDlg *Dlg);//将CChatDlg的对象传递给m_dlg
bool GetServerAddress();//将ip控件框里面的ip地址赋值给ServerAddress
bool GetSendBuf(CString SendData);//将发送框里面的内容赋值给SendBuf
bool GetReceiveBuf(CString & RecData);//将ReceiveBuf中的数据保存到一个cstring类型中
bool SendSound(char *buf,int len);//向服务器发送音频数据
};
#include "stdafx.h"
#include "Client.h"
#include "ChatDlg.h"
CClient::CClient(void)
{
}
CClient::~CClient(void)
{
}
///
// AddSocketLib-开始 //
// 加载套接字库 //
//
bool CClient::AddSocketLib()
{
WORD wVersion;
WSADATA wsaData;
int err;
wVersion=MAKEWORD(1,1);
err=::WSAStartup(wVersion,&wsaData);
if(err!=0)//如果调用失败
return false;
if(LOBYTE(wsaData.wVersion)!=1||HIBYTE(wsaData.wVersion)!=1)//如果调用失败
{
::WSACleanup();
return false;
}
return true;
}
///
// AddSocketLib-结束 //
// 加载套接字库 //
//
///
// CreateSocket-开始 //
// 创建监听套接字 //
//
bool CClient::CreateSocket()
{
//用于文字聊天
ClientSocket=::socket(AF_INET,SOCK_STREAM,0);
if(ClientSocket==INVALID_SOCKET)
return false;
//用于语音聊天
ClientSocketSound=::socket(AF_INET,SOCK_STREAM,0);
if(ClientSocketSound==INVALID_SOCKET)
return false;
return true;
}
///
// CreateSocket-结束 //
// 创建监听套接字 //
//
///
// ConnectSocket-开始 //
// 连接到服务器 //
//
bool CClient::ConnectSocket()
{
//用于文字聊天
if(::connect(ClientSocket,(SOCKADDR*)&ServerAddress,sizeof(SOCKADDR))==SOCKET_ERROR)
return false;
//用于语音聊天
if(::connect(ClientSocketSound,(SOCKADDR*)&ServerAddSound,sizeof(SOCKADDR))==SOCKET_ERROR)
return false;
return true;
}
///
// ConnectSocket-结束 //
// 连接到服务器 //
//
///
// SendData-开始 //
// 向客户端发送数据 //
//
bool CClient::SendData(WAVEHDR* p)
{
if(p==NULL)//用于文字聊天
{
if(::send(ClientSocket,SendBuf,::strlen(SendBuf)+1,0)==SOCKET_ERROR)
return false;
}
else//用于语音聊天
{
if(::send(ClientSocketSound,(char *)p,sizeof(WAVEHDR)+MAX_BUFFER_SIZE,0)==SOCKET_ERROR)
return false;
}
return true;
}
///
// SendData-结束 //
// 向客户端发送数据 //
//
///
// ReceiveData-开始 //
// 接收客户端发来的数据 //
//
bool CClient::ReceiveData(WAVEHDR* p)
{
if(p==NULL)
{
if(::recv(ClientSocket,ReceiveBuf,BUFSIZE,0)==SOCKET_ERROR)
return false;
}
else
{
// p=(WAVEHDR *)malloc(sizeof(WAVEHDR)+MAX_BUFFER_SIZE);
::recv(ClientSocketSound,(char *)p,sizeof(WAVEHDR)+MAX_BUFFER_SIZE,0);
}
return true;
}
///
// ReceiveData-结束 //
// 接收客户端发来的数据 //
//
///
// InitM_dlg-开始 //
// 将CChatDlg的对象传递给m_dlg //
//
bool CClient::InitM_dlg(CChatDlg *Dlg)
{
m_dlg=Dlg;
return true;
}
///
// InitM_dlg-结束 //
// 将CChatDlg的对象传递给m_dlg //
//
///
// GetServerAddress-开始 //
// 将ip控件框里面的ip地址赋值给ServerAddress //
//
bool CClient::GetServerAddress()
{
((CIPAddressCtrl *)(m_dlg->GetDlgItem(IDI_IPADDRESS)))->GetAddress(ServerAddress.sin_addr.s_addr);
ServerAddress.sin_addr.s_addr=::inet_addr("192.168.177.29");
ServerAddress.sin_family=AF_INET;
ServerAddress.sin_port=7000;
((CIPAddressCtrl *)(m_dlg->GetDlgItem(IDI_IPADDRESS)))->GetAddress(ServerAddSound.sin_addr.s_addr);
ServerAddSound.sin_addr.s_addr=::inet_addr("192.168.177.29");
ServerAddSound.sin_family=AF_INET;
ServerAddSound.sin_port=7000+1;
return true;
}
///
// GetServerAddress-结束 //
// 将ip控件框里面的ip地址赋值给ServerAddress //
//
///
// GetSendBuf-开始 //
// 将发送框里面的内容赋值给SendBuf //
//
bool CClient::GetSendBuf(CString SendData)
{
if(::sprintf(SendBuf,"%s",SendData)==-1)
return false;
return true;
}
///
// GetSendBuf-结束 //
// 将发送框里面的内容赋值给SendBuf //
//
///
// GetReceiveBuf-开始 //
// 将ReceiveBuf中的数据保存到一个cstring类型中 //
//
bool CClient::GetReceiveBuf(CString &RecData)
{
CString temp;
temp.Format("%s",ReceiveBuf);
RecData=RecData+" 服务器:"+temp+"/r/n";
return true;
}
///
// GetReceiveBuf-结束 //
// 将ReceiveBuf中的数据保存到一个cstring类型中 //
//
///
// SendSound-开始 //
// 向服务器发送音频数据 //
//
bool CClient::SendSound(char *buf,int len)
{
if(::send(ClientSocket,buf,len,0)==SOCKET_ERROR)
return false;
return true;
}
///
// SendSound-结束 //
// 向服务器发送音频数据 //
//
#include"Public.h"
#pragma once
//#include"ChatDlg.h"
#define BUFSIZE 1000
class CChatDlg;
class CServer
{
public:
//用于文字聊天定义-开始///
SOCKET ListenSocket; //用于服务器进行监听的套接字
SOCKET ConnectSocket; //服务器连接成功后,用于传输数据的套接字
struct sockaddr_in ServerAddress;//服务器的ip地址以及端口号
struct sockaddr_in ClientAddress;//客户端的ip地址以及端口号
char SendBuf[BUFSIZE];//发送缓存大小
char ReceiveBuf[BUFSIZE];//接收缓存大小
//用于文字聊天定义-结束///
//用于语音聊天定义-开始///
SOCKET ListenSocketSound;//用于服务器的音频聊天进行监听的套接字
SOCKET ConnectSocketSound;//服务器连接成功后,用于传输音频聊天的套接字
struct sockaddr_in ServerAddSound;//用于进行音频聊天的服务器的ip地址以及端口号
struct sockaddr_in ClientAddSound;//用于进行音频聊天的客户端的ip地址以及端口号
//用于语音聊天定义-结束///
CChatDlg *m_dlg;
public:
CServer(void);
~CServer(void);
bool AddSocketLib();//加载套接字库
bool CreateSocket();//创建监听套接字
bool BindSocket();//绑定套接字到ServerAddress
bool ListeSocket();//将套接字设置为监听模式,准备接收客户请求
bool AcceptClient();//等待客户端请求
bool SendData(WAVEHDR* p);//向客户端发送数据
bool ReceiveData(WAVEHDR* p);//接收客户端发来的数据
bool InitM_dlg(CChatDlg *Dlg);//将CChatDlg的对象传递给m_dlg
bool GetServerAddress();//将ip控件框里面的ip地址赋值给ServerAddress
bool GetSendBuf(CString SendData);//将发送框里面的内容赋值给SendBuf
bool GetReceiveBuf(CString & RecData);//将ReceiveBuf中的数据保存到一个cstring类型中
bool SendSound(char *buf,int len);//向客户端发送音频数据
};
#include "stdafx.h"
#include "Server.h"
#include"ChatDlg.h"
CServer::CServer(void)
: m_dlg(NULL)
{
}
CServer::~CServer(void)
{
}
///
// AddSocketLib-开始 //
// 加载套接字库 //
//
bool CServer::AddSocketLib()
{
WORD wVersion;
WSADATA wsaData;
int err;
wVersion=MAKEWORD(1,1);
err=::WSAStartup(wVersion,&wsaData);
if(err!=0)//如果调用失败
return false;
if(LOBYTE(wsaData.wVersion)!=1||HIBYTE(wsaData.wVersion)!=1)//如果调用失败
{
::WSACleanup();
return false;
}
return true;
}
///
// AddSocketLib-结束 //
// 加载套接字库 //
//
///
// CreateSocket-开始 //
// 创建监听套接字 //
//
bool CServer::CreateSocket()
{
ListenSocket=::socket(AF_INET,SOCK_STREAM,0);
ListenSocketSound=::socket(AF_INET,SOCK_STREAM,0);
if(ListenSocket==INVALID_SOCKET||ListenSocketSound==INVALID_SOCKET)
return false;
return true;
}
///
// CreateSocket-结束 //
// 创建监听套接字 //
//
///
// BindSocket-开始 //
// 绑定套接字到ServerAddress //
//
bool CServer::BindSocket()
{
if(::bind(ListenSocket,(SOCKADDR*)&ServerAddress,sizeof(SOCKADDR))==SOCKET_ERROR)//函数调用成功返回0,失败返回SOCKET_ERROR
return false;
if(::bind(ListenSocketSound,(SOCKADDR*)&ServerAddSound,sizeof(SOCKADDR))==SOCKET_ERROR)
return false;
return true;
}
///
// BindSocket-结束 //
// 绑定套接字到ServerAddress //
//
///
// ListenSoket-开始 //
// 将套接字设置为监听模式,准备接收客户请求 //
//
bool CServer::ListeSocket()
{
if(::listen(ListenSocket,5)==SOCKET_ERROR)
return false;
if(::listen(ListenSocketSound,5)==SOCKET_ERROR)
return false;
return true;
}
///
// ListenSoket-结束 //
// 将套接字设置为监听模式,准备接收客户请求 //
//
///
// AcceptClient-开始 //
// 等待客户端请求 //
//
bool CServer::AcceptClient()
{
//用于文字聊天的套接字
int Len=sizeof(SOCKADDR);//必须初始化为这个值,否则accept函数会调用失败
ConnectSocket=::accept(ListenSocket,(SOCKADDR*)&ClientAddress,&Len);
if(ConnectSocket==INVALID_SOCKET)
return false;
//用于语音聊天的套接字
int LenS=sizeof(SOCKADDR);//必须初始化为这个值,否则accept函数会调用失败
ConnectSocketSound=::accept(ListenSocketSound,(SOCKADDR*)&ClientAddSound,&LenS);
if(ConnectSocketSound==INVALID_SOCKET)
return false;
return true;
}
///
// AcceptClient-结束 //
// 等待客户端请求 //
//
///
// SendData-开始 //
// 向客户端发送数据 //
//
bool CServer::SendData(WAVEHDR* p)
{
if(p==NULL)
{
if(::send(ConnectSocket,SendBuf,::strlen(SendBuf)+1,0)==SOCKET_ERROR)
return false;
}
else
{
if(::send(ConnectSocketSound,(char *)p,sizeof(WAVEHDR)+MAX_BUFFER_SIZE,0)==SOCKET_ERROR)
return false;
}
return true;
}
///
// SendData-结束 //
// 向客户端发送数据 //
//
///
// ReceiveData-开始 //
// 接收客户端发来的数据 //
//
bool CServer::ReceiveData(WAVEHDR* p)
{
if(p==NULL)
{
if(::recv(ConnectSocket,ReceiveBuf,BUFSIZE,0)==SOCKET_ERROR)
return false;
}
else
{
if(::recv(ConnectSocketSound,(char *)p,sizeof(WAVEHDR)+MAX_BUFFER_SIZE,0)==SOCKET_ERROR)
return false;
}
return true;
}
///
// ReceiveData-结束 //
// 接收客户端发来的数据 //
//
///
// InitM_dlg-开始 //
// 将CChatDlg的对象传递给m_dlg //
//
bool CServer::InitM_dlg(CChatDlg *Dlg)
{
m_dlg=Dlg;
return true;
}
///
// InitM_dlg-结束 //
// 将CChatDlg的对象传递给m_dlg //
//
///
// GetServerAddress-开始 //
// 将ip控件框里面的ip地址赋值给ServerAddress //
//
bool CServer::GetServerAddress()
{
用于传输文字聊天数据的socket-开始/
((CIPAddressCtrl *)m_dlg->GetDlgItem(IDI_IPADDRESS))->
GetAddress(ServerAddress.sin_addr.S_un.S_un_b.s_b1,
ServerAddress.sin_addr.S_un.S_un_b.s_b2,
ServerAddress.sin_addr.S_un.S_un_b.s_b3,
ServerAddress.sin_addr.S_un.S_un_b.s_b4);
CString temp;
((CEdit *)m_dlg->GetDlgItem(IDE_PORT))->GetWindowTextA(temp);
ServerAddress.sin_port=::atol(temp);
ServerAddress.sin_family=AF_INET;
用于传输文字聊天数据的socket-结束/
用于传输语音聊天数据的socket-开始/
((CIPAddressCtrl *)m_dlg->GetDlgItem(IDI_IPADDRESS))->
GetAddress(ServerAddSound.sin_addr.S_un.S_un_b.s_b1,
ServerAddSound.sin_addr.S_un.S_un_b.s_b2,
ServerAddSound.sin_addr.S_un.S_un_b.s_b3,
ServerAddSound.sin_addr.S_un.S_un_b.s_b4);
ServerAddSound.sin_port=::atol(temp)+1;//必须与文字聊天是不同的端口号
ServerAddSound.sin_family=AF_INET;
用于传输语音聊天数据的socket-结束/
return true;
}
///
// GetServerAddress-结束 //
// 将ip控件框里面的ip地址赋值给ServerAddress //
//
///
// GetSendBuf-开始 //
// 将发送框里面的内容赋值给SendBuf //
//
bool CServer::GetSendBuf(CString SendData)
{
if(::sprintf(SendBuf,"%s",SendData)==-1)
return false;
return true;
}
///
// GetSendBuf-结束 //
// 将发送框里面的内容赋值给SendBuf //
//
///
// GetReceiveBuf-开始 //
// 将ReceiveBuf中的数据保存到一个cstring类型中 //
//
bool CServer::GetReceiveBuf(CString &RecData)
{
CString temp;
temp.Format("%s",ReceiveBuf);
RecData=RecData+" 客户端:"+temp+"/r/n";
return true;
}
///
// GetReceiveBuf-结束 //
// 将ReceiveBuf中的数据保存到一个cstring类型中 //
//
///
// SendSound-开始 //
// 向客户端发送音频数据 //
//
bool CServer::SendSound(char *buf,int len)
{
if(::send(ConnectSocket,buf,len,0)==SOCKET_ERROR)
return false;
return true;
}
///
// SendSound-结束 //
// 向客户端发送音频数据 //
//
//#include"Public.h"
#include"ChatDlg.h"
#ifndef _Sound_h_//用于防止头文件嵌套多次1
#define _Sound_h_//用于防止头文件嵌套多次2
#define BUFNUM 10
#define MAX_BUFFER_SIZE 2048
#pragma once
//class CChatDlg;
class CSound
{
public:
WAVEFORMATEX m_soundFormat;//存储录音以及播放格式的相关信息
HWAVEIN m_hWaveIn; //输入设备句柄
HWAVEOUT m_hWaveOut; //输出设备句柄
WAVEHDR* m_bufferIn[BUFNUM];//用于录音的内存的相关信息
WAVEHDR* m_bufferOut[BUFNUM];//用于播放的内存的相关信息
bool m_Outusingflag[BUFNUM];//标识m_bufferOut是否已经与输出设备联系起来!没有为false,有为true
public:
CSound(void);
~CSound(void);
bool Init(CChatDlg *m_dlg);//初始化音频输入、输出设备
bool Record();//录音
bool StopRecord();//停止录音
bool Play(WAVEHDR *pWaveData);//播放
bool FreeRecordBuffer(WAVEHDR *pWaveInBuffer);//释放音频输入设备和pWaveInBuffer指向缓存之间的联系
bool AddRecordBuffer(WAVEHDR *pWaveInBuffer);//添加音频输入设备和pWaveInBuffer指向缓存之间的联系
bool FreePlayBuffer(WAVEHDR *pWaveInBuffer);//释放音频输出设备和pWaveInBuffer指向缓存之间的联系
};
#endif//用于防止头文件嵌套多次3
#include "stdafx.h"
#include "Sound.h"
CSound::CSound(void)
{
}
CSound::~CSound(void)
{
}
///
// Init-开始 //
// 初始化音频输入、输出设备 //
//
bool CSound::Init(CChatDlg *m_dlg)
{
if(::waveInGetNumDevs()==0)//获取音频输入设备的数量
{
::AfxMessageBox("There is no input device!");
return false;
}
if(::waveOutGetNumDevs()==0)//获取音频输出设备的数量
{
::AfxMessageBox("There is no output device!");
return false;
}
//设置录音参数—开始//
m_soundFormat.wFormatTag=WAVE_FORMAT_PCM;
m_soundFormat.nChannels=1;
m_soundFormat.nSamplesPerSec=8000;
m_soundFormat.nAvgBytesPerSec=16000;
m_soundFormat.nBlockAlign=2;
m_soundFormat.cbSize=0;
m_soundFormat.wBitsPerSample=16;
//设置录音参数—结束//
int result=::waveInOpen(&m_hWaveIn,WAVE_MAPPER,&m_soundFormat,//打开音频输入设备
(DWORD)m_dlg->m_hWnd,0L,CALLBACK_WINDOW);
if(result!=MMSYSERR_NOERROR)
{
::AfxMessageBox("Error in function waveInOpen!");
return false;
}
result=::waveOutOpen(&m_hWaveOut,WAVE_MAPPER,&m_soundFormat,//打开音频输出设备
(DWORD)m_dlg->m_hWnd,0L,CALLBACK_WINDOW);
if(result!=MMSYSERR_NOERROR)
{
::AfxMessageBox("Error in function waveOutOpen!");
return false;
}
//初始化m_bufferIn—开始//
for(int i=0;i<BUFNUM;i++)
{
m_bufferIn[i]=(WAVEHDR*)malloc(MAX_BUFFER_SIZE+sizeof(WAVEHDR));//分配WAVEHDR结构体加存储录音所需大小的内存
::ZeroMemory(m_bufferIn[i],sizeof(WAVEHDR));//将m_pcBufferIn[i]地址开始到sizeof(WAVEHDR)大小的空间赋值为0
m_bufferIn[i]->dwBufferLength=MAX_BUFFER_SIZE;//录音内存空间的大小
m_bufferIn[i]->lpData=(LPSTR)(m_bufferIn[i]+1);//指向录音内存空间的起始地址
m_bufferIn[i]->dwBytesRecorded=0;//现有录音空间的数据量
m_bufferIn[i]->dwFlags=0;//要调用waveInPrepareHeader必须设置为0
//准备内存块录音,把音频输入设备和用于存储录音的buffer联系起来
if(::waveInPrepareHeader(m_hWaveIn,m_bufferIn[i],sizeof(WAVEHDR))!=MMSYSERR_NOERROR)
{
::AfxMessageBox("Error in function waveInPrepareHeader!");
return false;
}
//指定m_hWaveIn音频输入设备的音频保存到m_pcBufferIn[i]所指向的内存
if(::waveInAddBuffer(m_hWaveIn,m_bufferIn[i],sizeof(WAVEHDR))!=MMSYSERR_NOERROR)
{
::AfxMessageBox("Error in function waveInAddBuffer!");
return false;
}
}
//初始化m_bufferIn—结束//
//初始化m_bufferOut—开始//
for(int i=0;i<BUFNUM;i++)
{
m_bufferOut[i] = (WAVEHDR*)malloc(MAX_BUFFER_SIZE+sizeof(WAVEHDR));//分配WAVEHDR结构体加存储录音所需大小的内存
ZeroMemory( m_bufferOut[i], sizeof(WAVEHDR) );//将m_pcBufferIn[i]地址开始到sizeof(WAVEHDR)大小的空间赋值为0
m_bufferOut[i]->dwBufferLength = MAX_BUFFER_SIZE;//录音内存空间的大小
m_bufferOut[i]->lpData = (LPSTR)(m_bufferIn[i] +1);//指向录音内存空间的起始地址
m_bufferOut[i]->dwBytesRecorded=0;//现有录音空间的数据量
m_bufferOut[i]->dwFlags=0;//要调用waveInPrepareHeader必须设置为0
m_Outusingflag[i]=false;
}
//初始化m_bufferOut—结束//
//stops playback on the given waveform-audio output device and
//resets the current position to zero. All pending playback buffers are marked as done and returned to the application.
waveOutReset(m_hWaveOut);
return true;
}
///
// Init-结束 //
// 初始化音频输入、输出设备 //
//
///
// Record-开始 //
// 录音 //
//
bool CSound::Record()
{
if(::waveInStart(m_hWaveIn)==MMSYSERR_NOERROR)//开始录音
{
return true;
}
return false;
}
///
// Record-结束 //
// 录音 //
//
///
// StopRecord-开始 //
// 停止录音 //
//
bool CSound::StopRecord()
{
if(::waveInStop(m_hWaveIn)==MMSYSERR_NOERROR&&
::waveInReset(m_hWaveIn)==MMSYSERR_NOERROR)
return true;
return false;
}
///
// StopRecord-结束 //
// 停止录音 //
//
///
// Play-开始 //
// 播放 //
//
bool CSound::Play(WAVEHDR *pWaveData)
{
for(int i=0;i<BUFNUM;i++)
{
if(m_Outusingflag[i]==false)
{
//复制pWaveData中的内容到m_pcBufferOut中
memcpy(m_bufferOut[i],pWaveData,sizeof(WAVEHDR)+pWaveData->dwBufferLength);
if(waveOutPrepareHeader(m_hWaveOut,m_bufferOut[i],sizeof(WAVEHDR))!= MMSYSERR_NOERROR)
{
::AfxMessageBox("Error in function waveOutPrepareHeader!");
return false;
}
//将一个内存块输给音频输出设备进行播放
if(waveOutWrite(m_hWaveOut,m_bufferOut[i],sizeof(WAVEHDR))!= MMSYSERR_NOERROR)
{
::AfxMessageBox("Erro in function waveOutWrite!");
return false;
}
m_Outusingflag[i]=true;
break;
}//if
}//for
return true;
}
///
// Play-结束 //
// 播放 //
//
///
// FreeRecordBuffer-开始 //
// 释放音频输入设备和缓存之间的联系 //
//
bool CSound::FreeRecordBuffer(WAVEHDR *pWaveInBuffer)
{
if(::waveInUnprepareHeader(m_hWaveIn,pWaveInBuffer,
sizeof(WAVEHDR))!=MMSYSERR_NOERROR)
{
::AfxMessageBox("Error in function waveInUnprepareHeader!");
return false;
}
return true;
}
///
// FreeRecordBuffer-结束 //
// 释放音频输入设备和缓存之间的联系 //
//
///
// AddRecordBuffer-开始 //
// 添加音频输入设备和缓存之间的联系 //
//
bool CSound::AddRecordBuffer(WAVEHDR *pWaveInBuffer)
{
pWaveInBuffer->dwBufferLength=MAX_BUFFER_SIZE;
if(::waveInPrepareHeader(m_hWaveIn,pWaveInBuffer,
sizeof(WAVEHDR))!=MMSYSERR_NOERROR)
{
::AfxMessageBox("Error in function waveInPrepareHeader!");
return false;
}
if(::waveInAddBuffer(m_hWaveIn,pWaveInBuffer,
sizeof(WAVEHDR))!=MMSYSERR_NOERROR)
{
::AfxMessageBox("Error in function waveInAddBuffer!");
return false;
}
return true;
}
///
// AddRecordBuffer-结束 //
// 添加音频输入设备和缓存之间的联系 //
//
///
// FreePlayBuffer-开始 //
// 释放音频输出设备和pWaveInBuffer指向缓存之间的联系 //
//
bool CSound::FreePlayBuffer(WAVEHDR *pWaveInBuffer)
{
if(::waveOutUnprepareHeader(m_hWaveOut,pWaveInBuffer,
sizeof(WAVEHDR))!=MMSYSERR_NOERROR)
{
::AfxMessageBox("Error in function waveOutUnprepareHeader!");
return false;
}
return true;
}
///
// FreePlayBuffer-结束 //
// 释放音频输出设备和pWaveInBuffer指向缓存之间的联系 //
//
// stdafx.cpp : 只包括标准包含文件的源文件
// Chat.pch 将作为预编译头
// stdafx.obj 将包含预编译类型信息
#include "stdafx.h"
//Public.h
#include"Resource.h"
#include"Mmsystem.h"
#include "afxsock.h"
#include <afxmt.h>
#include "Chat.h"
#include <mmsystem.h>
#include <afxmt.h>
//Resouce.h
//{{NO_DEPENDENCIES}}
// Microsoft Visual C++ generated include file.
// Used by Chat.rc
//
#define IDM_ABOUTBOX 0x0010
#define IDD_ABOUTBOX 100
#define IDS_ABOUTBOX 101
#define IDD_CHAT_DIALOG 102
#define IDR_MAINFRAME 128
#define IDE_CHAT 1000
#define IDE_EDITCHAT 1001
#define IDB_VOICECHAT 1002
#define IDC_SENDVOICE 1003
#define IDI_IPADDRESS 1004
#define IDE_PORT 1005
#define IDB_BUILDSERVER 1006
#define IDB_LINKSERVER 1007
#define IDB_SEND 1008
#define IDB_CLOSE 1009
#define IDE_BUILDSTATE 1011
#define IDC_LINKSTATE 1012
#define IDE_LINKSTATE 1012
// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 129
#define _APS_NEXT_COMMAND_VALUE 32771
#define _APS_NEXT_CONTROL_VALUE 1013
#define _APS_NEXT_SYMED_VALUE 101
#endif
#endif
// stdafx.h : 标准系统包含文件的包含文件,
// 或是经常使用但不常更改的
// 特定于项目的包含文件
#pragma once
#ifndef _SECURE_ATL
#define _SECURE_ATL 1
#endif
#ifndef VC_EXTRALEAN
#define VC_EXTRALEAN // 从 Windows 头中排除极少使用的资料
#endif
#include "targetver.h"
#define _ATL_CSTRING_EXPLICIT_CONSTRUCTORS // 某些 CString 构造函数将是显式的
// 关闭 MFC 对某些常见但经常可放心忽略的警告消息的隐藏
#define _AFX_ALL_WARNINGS
#include <afxwin.h> // MFC 核心组件和标准组件
#include <afxext.h> // MFC 扩展
#include <afxdisp.h> // MFC 自动化类
#ifndef _AFX_NO_OLE_SUPPORT
#include <afxdtctl.h> // MFC 对 Internet Explorer 4 公共控件的支持
#endif
#ifndef _AFX_NO_AFXCMN_SUPPORT
#include <afxcmn.h> // MFC 对 Windows 公共控件的支持
#endif // _AFX_NO_AFXCMN_SUPPORT
#ifdef _UNICODE
#if defined _M_IX86
#pragma comment(linker,"/manifestdependency:/"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='x86' publicKeyToken='6595b64144ccf1df' language='*'/"")
#elif defined _M_IA64
#pragma comment(linker,"/manifestdependency:/"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='ia64' publicKeyToken='6595b64144ccf1df' language='*'/"")
#elif defined _M_X64
#pragma comment(linker,"/manifestdependency:/"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='amd64' publicKeyToken='6595b64144ccf1df' language='*'/"")
#else
#pragma comment(linker,"/manifestdependency:/"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'/"")
#endif
#endif
//targetver.h
#pragma once
// 以下宏定义要求的最低平台。要求的最低平台
// 是具有运行应用程序所需功能的 Windows、Internet Explorer 等产品的
// 最早版本。通过在指定版本及更低版本的平台上启用所有可用的功能,宏可以
// 正常工作。
// 如果必须要针对低于以下指定版本的平台,请修改下列定义。
// 有关不同平台对应值的最新信息,请参考 MSDN。
#ifndef WINVER // 指定要求的最低平台是 Windows Vista。
#define WINVER 0x0600 // 将此值更改为相应的值,以适用于 Windows 的其他版本。
#endif
#ifndef _WIN32_WINNT // 指定要求的最低平台是 Windows Vista。
#define _WIN32_WINNT 0x0600 // 将此值更改为相应的值,以适用于 Windows 的其他版本。
#endif
#ifndef _WIN32_WINDOWS // 指定要求的最低平台是 Windows 98。
#define _WIN32_WINDOWS 0x0410 // 将此值更改为适当的值,以适用于 Windows Me 或更高版本。
#endif
#ifndef _WIN32_IE // 指定要求的最低平台是 Internet Explorer 7.0。
#define _WIN32_IE 0x0700 // 将此值更改为相应的值,以适用于 IE 的其他版本。
#endif
局域网聊天软件源代码(包括语音聊天)相关推荐
- 高仿Telegram IM Chat 聊天软件 即时通讯 在线聊天加社群 纯静态UI架构介绍
高仿Telegram IM Chat 聊天软件 即时通讯 在线聊天加社群 纯静态UI 全端覆盖!苹果手机端.安卓手机端.网页版.电脑PC版.无论哪个平台,都能畅通无阻! 性价比高!功能全面而价格低廉! ...
- Android聊天软件的开发(七)--聊天通信
聊天通信通过Socket实现,大概的框架如下图: 通信流程: 1.服务器在启动时开启聊天服务线程 可以通过ServletContextListener监听Servlet的初始化和销毁,来开启和关闭聊天 ...
- java 聊天工具源代码_简易聊天软件源码
[java]代码库import java.io.*; import java.net.*; import java.util.*; public class ChatServer { boolean ...
- 手机版_仿微信 陌陌 安卓版(android)/苹果版(iPhone ios),移动社交APP系统源码,企业即时通讯APP程序源码,手机聊天软件源码,移动聊天APP开发...
一:系统背景 根据国际电信联盟发布的<衡量信息社会发展报告>中显示:2014年全球手机用户已超过70亿人,全球互联网用户已超过30亿人,世界上移动通信设备用户总数已超过世界总人口数(还在稳 ...
- 用Delphi开发视频聊天软件
一.引言 我们知道视频聊天软件的关键技术在于采集视频,并实时传输给聊天软件在线的人.对于视频的采集,这里采用微软公司的关于数字视频的一个软件包VFW(Video for Windows).相信很多人对 ...
- C#毕业设计——基于C#+vs.net+SQL Server的多功能聊天软件设计与实现(毕业论文+程序源码)——多功能聊天软件
基于C#+vs.net+SQL Server的多功能聊天软件设计与实现(毕业论文+程序源码) 大家好,今天给大家介绍基于C#+vs.net+SQL Server的多功能聊天软件设计与实现,文章末尾附有 ...
- 做简单的android 软件推荐,Android_适用于Android开发的简单聊天软件,适用于android 开发。是一个简 - phpStudy...
适用于Android开发的简单聊天软件 适用于android 开发.是一个简单的聊天软件,包括知识点,各个控件的运用(ExpandableListView,ViewPager,Spinner,Line ...
- 爱聊语音聊天室为什么用不了摄像头?
很多朋友反映自己上自己的qq可以进行视频语音聊天室的,可是为什么进入了爱聊语音聊天室之后这个摄像头功能却没有作用,杭州雅顾视频语音聊天室服务商特意借大家这几个问问题为大家想解下,一般进爱聊语音聊天室这 ...
- 语音聊天室资料(一)
互联网的普及给现代人带来了极大的方便,人们除了可以在网上看新闻.发电邮.购物.查资料等等,最重要的是可通过互联网与家人.亲戚.朋友或陌生人在线交流.现在比较流行的交流方式大概有ICQ式.文字聊天室.网 ...
最新文章
- 有空间感的图片环形滚动代码
- 史上最全GAN综述2020版:算法、理论及应用
- LSTM模型在问答系统中的应用 2017-06-27 21:03 在问答系统的应用中,用户输入一个问题,系统需要根据问题去寻找最合适的答案。 1:采用句子相似度的方式。根据问题的字面相似度选择相似度最
- 殷拓联手红星美凯龙收购软装家具企业“墙尚”40%股份​
- 威联通装linux百度网盘,威联通NAS使用百度云Docker教程,超简单!
- 考研失败了,怎么办?
- ajax前端实时获取数据
- Java架构师面试问些什么?微服务之springcloud面试题(共22题,含详细解答)
- 软件测试--网络协议(三)
- zabbix-将业务机器加入到监控中
- EXCEL-批量下拉填充
- LINUX论坛快速搭建(小白版)
- JavaScript完成知乎页面
- 基于DRM框架的HDMI热插拔流程分析
- 使用canvas画二维码
- 用html5做一个视频网页,如何使用HTML5在网页上制作交互式视频?
- 我的Android进阶之旅------/storage/sdcard0, /sdcard, /mnt/sdcard ,/storage/emulated/legacy 的区别
- Codeforces——791A Bear and Big Brother
- LaTeX学习 |(15)LaTeX 自定义环境和命令
- PERT图(工程网络图)
热门文章
- Android动画总结系列(2)——补间动画使用
- java switch case null_如何在switch中使用null
- C:\WINDOWS\system32\Macromed\Flash\Flash32_11_5_502_110.ocx
- 2022年4月23日美团笔试
- 我与Java的那些年和那些事
- CSS中子选择器和后代选择器之间有什么区别
- 谷歌浏览器密码导入导出
- Xmind教程-添加外框
- Docker报错:E: Unable to locate package python3
- 产业链图谱:2021年中国5G产业链图谱|产业链全景图