4.1.2 文字聊天实现 ChatServer服务器运行时,利用一个CSocket对象CSocketServer启动服务器,用函数gethostname来获得服务器端主机名和IP,同时在服务器对话框中显示服务器IP,并将分配的固定端口号8123显示在对话框中。用一个list列表显示在线用户,随时更新用户登录情况,用一个edit box显示客户端的聊天内容以及系统提示消息。每一个ChatClient客户端启动时,利用服务器内定的用户号和密码来登录(如图6)。在整个系统中,利用链表来处理所有的用户信息:当有用户登录时,在链表尾部加入该用户信息;当用户下线时,在该链表中删除用户,并提示所有用户,该用户下线。在对链表进行操作的同时,要更新list列表中的信息。 copyright paper51.com
内容来自论文无忧网 www.paper51.com
图6 用户登录界面 copyright paper51.com ChatServer服务器端响应客户端文字聊天时的中转情况如图7。 paper51.com
copyright paper51.com
图7 服务器响应文字聊天信息中转 http://www.paper51.com ChatClient客户端两两间进行文字聊天时,发送信息的处理函数如下: 内容来自论文无忧网 www.paper51.com void CChatClientDlg::OnChatBtSend() //发送信息按键 内容来自www.paper51.com { 内容来自论文无忧网 www.paper51.com
if(!m_bConnect) paper51.com { copyright paper51.com SetMessageBox("请连接服务器!\r\n"); 内容来自论文无忧网 www.paper51.com
return; http://www.paper51.com } copyright paper51.com CStringstr; paper51.com
CStringszUserName; http://www.paper51.com CMesgmsg; copyright paper51.com GetDlgItemText(IDC_MESSAGE,str); 内容来自论文无忧网 www.paper51.com GetDlgItemText(IDC_USERNAME,szUserName); copyright paper51.com if(str.GetLength() <= 0 ) http://www.paper51.com { paper51.com SetMessageBox("请输入想要发送的信息!\r\n"); 内容来自www.paper51.com
return; paper51.com } 内容来自论文无忧网 www.paper51.com if( szUserName.GetLength() <= 0) http://www.paper51.com { 内容来自www.paper51.com SetMessageBox("请选择说话对象!\r\n"); 内容来自论文无忧网 www.paper51.com return; http://www.paper51.com } 内容来自论文无忧网 www.paper51.com //消息封装 paper51.com
msg.m_szCommand.Format("Message"); 内容来自论文无忧网 www.paper51.com msg.m_szRecObject.Format(szUserName); http://www.paper51.com
msg.m_szText.Format(str); http://www.paper51.com m_csClient->SendM(&msg); 内容来自www.paper51.com AddReceiver(szUserName, true); 内容来自www.paper51.com AddChatMessage(str); http://www.paper51.com } copyright paper51.com
在聊天两个客户端的信息情况如图8和图9。 内容来自www.paper51.com
paper51.com
图8 接收文字信息 内容来自论文无忧网 www.paper51.com
paper51.com 图9 发送文字信息 内容来自论文无忧网 www.paper51.com 4.2 语音视频聊天4.2.1 UDP套接字的运用 http://www.paper51.com 在实现语音视频聊天时,采用的是基于UDP套接字的点对点模式,而UDP面向的是无连接的数据服务,其套接字的使用如图10所示。 http://www.paper51.com
内容来自www.paper51.com 图10 UDP套接字的使用 内容来自www.paper51.com 4.2.2 视频的捕获 内容来自论文无忧网 www.paper51.com 利用VFW接口,视频捕获可以分为以下几个步骤: 内容来自论文无忧网 www.paper51.com (1) 建立视频采集窗口:该窗口用来接收视频捕捉驱动程序传来的数据和消息。 http://www.paper51.com
(2) 连接视频驱动程序:将建立的视频捕捉窗口与视频设备驱动程序相连。 内容来自www.paper51.com (3) 视频捕获初始化。 paper51.com (4) 视频捕捉设置:VFW下视频捕捉参数的设置可以通过调用函数或弹出对话框的形式来实现。一般视频驱动程序允许设置的参数包括视频源选择、视频格式、视频显示格式等。 copyright paper51.com (5) 设置回调函数:通过回调函数来通知程序视频事件的发生,比如捕捉一帧图像成功的消息,捕捉出错的消息等。 内容来自论文无忧网 www.paper51.com (6) 结束捕捉:结束捕捉是应该有一些清除工作。如释放分配的内存,断开捕捉窗口与视频捕捉驱动程序的连接,清除视频捕捉窗口等。 内容来自www.paper51.com 窗口类为捕获数字视频流及其相关操作提供了很大的方便,灵活编写其中的回调函数可满足实时视频传输的需要,例如应用程序可直接从缓冲中取得数字视频并对其进行压缩编码后实时地传到远端的客户端。 内容来自论文无忧网 www.paper51.com 在VC++中,采用VFW技术,客户端通过capSetCallbackOnFrame()注册回调函数,当采集卡采集到一幅图像后,系统就会自动调用回调函数,然后再回调函数中使用ICSeqCompressFrame()函数进行压缩。然后再通过Winsock将压缩后的数据发送到另一客户端。该客户端接收完一帧以后,交给ICDecompress()解压,最后用SetDIBitsToDevice()将图像显示出来。 http://www.paper51.com 基本的捕获设置包括设置捕获速度(每秒捕获多少帧)、是否同时捕获声频、捕获缓冲、允许最大丢失多少帧和是否使用DOS内存,以及使用键盘的哪个键或鼠标的哪个键来终止捕获等内容,这些设置使用CAPTUREPARAMS结构来描述,capCaptureGetSetup宏来得到当前的设置,然后改变此结构的成员变量,再使用capCaptureSetSetup宏设置新的设置。 http://www.paper51.com 设置捕获速度,通过使用capCaptureGetSetup宏来得到当前的捕捉速度,将当前的捕捉速度保存在CAPTUREPARAMS结构的dwRequestMicroSecPerFrame成员变量中,也可以通过设置此变量来改变当前设置值。 paper51.com 设置终止捕获,同样通过使用capCaptureGetSetup宏来得到当前的设置,当前按键设置保存在CAPTUREPARAMS结构的vKeyAbort成员中,鼠标设置保存在fAbortLeftMouse和fAbortRightMouse成员中,通过修改可以设置新的热健或者鼠标左右键,修改完成后,使用capCaptureSetSetup宏来进行更新。 内容来自论文无忧网 www.paper51.com 捕获的时间限制,用CAPTUREPARAMS结构中的fLimitEnabled表示捕获是否有时间的限制,wTimeLimit用来设置指示捕获最大的持续时间,其单位为秒。使用capCaptureGetSetup宏来得到当前的设置值。 内容来自论文无忧网 www.paper51.com 下面程序为设置CAPTUREPARAMS结构的实现代码: 内容来自论文无忧网 www.paper51.com BOOL VideoCapture::SetCapturePara() copyright paper51.com { http://www.paper51.com CAPTUREPARMSCapParms={0}; 内容来自论文无忧网 www.paper51.com capCaptureGetSetup(m_capwnd,&CapParms,sizeof(CapParms)); paper51.com
//得到当前的捕获速度 内容来自论文无忧网 www.paper51.com CapParms.fAbortLeftMouse= FALSE; 内容来自论文无忧网 www.paper51.com CapParms.fAbortRightMouse= FALSE; 内容来自论文无忧网 www.paper51.com CapParms.fYield= TRUE; http://www.paper51.com CapParms.fCaptureAudio= FALSE; http://www.paper51.com CapParms.wPercentDropForError= 80; 内容来自论文无忧网 www.paper51.com
if(!capCaptureSetSetup(m_capwnd,&CapParms,sizeof(CapParms))) 内容来自www.paper51.com
{ copyright paper51.com // log.WriteString("\nFailed to set the capture parameters "); copyright paper51.com returnFALSE; paper51.com } http://www.paper51.com //Set Video Format paper51.com capGetVideoFormat(m_capwnd,&m_bmpinfo,sizeof(m_bmpinfo)); paper51.com
m_bmpinfo.bmiHeader.biWidth=IMAGE_WIDTH; 内容来自www.paper51.com
m_bmpinfo.bmiHeader.biHeight=IMAGE_HEIGHT; copyright paper51.com BOOLret=capSetVideoFormat(m_capwnd,&m_bmpinfo,sizeof(m_bmpinfo)); copyright paper51.com // log.WriteString("\nVideo parameters set properly"); paper51.com
returnret; paper51.com } 内容来自www.paper51.com //终止一个捕获任务 copyright paper51.com
BOOL VideoCapture::StopCapture() http://www.paper51.com
{ 内容来自论文无忧网 www.paper51.com capCaptureStop(m_capwnd); 内容来自论文无忧网 www.paper51.com capCaptureAbort(m_capwnd); 内容来自www.paper51.com Sleep(500); http://www.paper51.com return TRUE; 内容来自www.paper51.com } 内容来自论文无忧网 www.paper51.com |