最新文章专题视频专题问答1问答10问答100问答1000问答2000关键字专题1关键字专题50关键字专题500关键字专题1500TAG最新视频文章推荐1 推荐3 推荐5 推荐7 推荐9 推荐11 推荐13 推荐15 推荐17 推荐19 推荐21 推荐23 推荐25 推荐27 推荐29 推荐31 推荐33 推荐35 推荐37视频文章20视频文章30视频文章40视频文章50视频文章60 视频文章70视频文章80视频文章90视频文章100视频文章120视频文章140 视频2关键字专题关键字专题tag2tag3文章专题文章专题2文章索引1文章索引2文章索引3文章索引4文章索引5123456789101112131415文章专题3
当前位置: 首页 - 正文

基于Socket的即时通讯系统

来源:动视网 责编:小OO 时间:2025-09-27 08:12:12
文档

基于Socket的即时通讯系统

评阅教师评语:课程设计成绩考勤成绩实做成绩报告成绩总评成绩指导教师签名:《综合课程设计》设计报告论文题目:基于Socket的即时通讯系统学院(系):班级:学生姓名:学号指导教师:时间:2011年6月7日到2011年6月17日一、设计题目基于Socket的即时通讯系统二、设计目的通过综合课程设计,使学生能够运用《数字信号处理》、《信号与系统》、《通信原理》、《面向对象的程序设计》、《计算机通信网》、《通信协议开发及应用》等课程的知识来设计一个基于Socket的即时通讯系统,培养学生的动手能力以及
推荐度:
导读评阅教师评语:课程设计成绩考勤成绩实做成绩报告成绩总评成绩指导教师签名:《综合课程设计》设计报告论文题目:基于Socket的即时通讯系统学院(系):班级:学生姓名:学号指导教师:时间:2011年6月7日到2011年6月17日一、设计题目基于Socket的即时通讯系统二、设计目的通过综合课程设计,使学生能够运用《数字信号处理》、《信号与系统》、《通信原理》、《面向对象的程序设计》、《计算机通信网》、《通信协议开发及应用》等课程的知识来设计一个基于Socket的即时通讯系统,培养学生的动手能力以及

评阅教师评语:课程设计成绩
考勤成绩
实做成绩
报告成绩
总评成绩
指导教师签名:
《综合课程设计》

设 计 报 告

论文题目:    基于Socket的即时通讯系统     

          

       

学院(系):                           

班    级:                            

学生姓名:               学号         

指导教师:                            

       

时间: 2011 年 6月 7日 到 2011 年 6 月 17 日

一、设计题目

基于Socket的即时通讯系统

二、设计目的

通过综合课程设计,使学生能够运用《数字信号处理》、《信号与系统》、《通信原理》、《面向对象的程序设计》、《计算机通信网》、《通信协议开发及应用》等课程的知识来设计一个基于Socket的即时通讯系统,培养学生的动手能力以及分析问题、解决问题的能力。

三、设计要求

(一)基本要求

1.熟练掌握面向对象的程序设计方法;

2.实现点对点通讯,能进行文字对话传输,包括客户端与服务器端;

3.能对系统参数进行配置。

(二)提高要求

1、实现文件、图片传输;

2、语音对话(两人及两人以上);

3、友好的对话界面。

四、 设计原理

Socket原理,大致分为以下几个步骤。

服务器端的步骤如下。

(1)首先,在实用Socket之前,要首先初始化Socket,就是实用AfxSocketInit()函数。

(2)在初始化完成以后,就可以建立服务端的Socket,然后实用该Sokcet开始侦听整个网络中的连接请求。

(3)当检测到来自客户端的连接请求时,向客户端发送收到连接请求的信息,并建立与客户端之间的连接。连接的过程中,在MFC的框架中会触发一个前面创建的服务端Socket的消息响应函数OnAccept(),我们将建立的连接的代码放到该响应函数里面,在建立连接的过程中,会产生一个新的 Socket,我们使用找个Socket来进行数据的通信。

(4)在通信的过程中,服务器端的产生的新的Socket会通过一个消息响应函数OnReceive()来接受到达的数据。数据的发送可以使用Send()来完成

(5)当完成通信后,服务器关闭与客户端的Socket连接。

客户端的步骤如下。

(1)同样的,初始化Socket,并建立客户端的Socket,确定要连接的服务器的主机名和端口。

(2)发送连接请求到服务器(MFC中使用Connect()),并等待服务器的回馈信息。

(3)连接成功后,与服务器进行数据的交互。

(4)数据的读取同服务端一样,也是通过OnReceive()来完成的,数据的发送通过Send()即可。

(5)数据处理完毕后,关闭自身的Socket连接。

5、 软件设计

6、 调试过程

七、 实验结果分析

一,如何更好的检测TCP连接是否正常

这方面问题,我上网查了很久,一般来说比较成熟的有两种方法:

1是在应用层制定协议,发心跳包,这也是C#,JAVA等高级语言比较常用的方法。客户端和服务端制定一个通讯协议,每隔一定时间(一般15秒左右),由一方发起,向对方发送协议包;对方收到这个包后,按指定好的通讯协议回一个。若没收到回复,则判断网络出现问题,服务器可及时的断开连接,客户端也可以及时重连。

2通过TCP协议层发送KeepAlive包。这个方法只需设置好你使用的TCP的KeepAlive项就好,其他的操作系统会帮你完成。操作系统会按时发送KeepAlive包,一发现网络异常,马上断开。我就是使用这个方法,也是重点向大家介绍的。

使用第二种方法的好处,是我们在应用层不需自己定协议,通信的两端,只要有一端设好这个值,两边都能及时检测出TCP连接情况。而且这些都是操作系统帮你自动完成的。

八、 体会和建议

通过这次课程设计,让我加深了对面向对象编程的了解,通过使用dephi编程,掌握了它的的基本应用,也懂得了要想熟练编程不是一朝一夕的事情,一份付出一份收获,只有加强以后的上机编程时间,才能让自己的编程能力的到进一步的提高。此外,利用Delphi 下的Socket 控件,可以很好地解决局域网内的实时通信问题,目前在各中小企事业单位中已经得到广泛应用. 系统具有良好的扩充性,例如可实现对信息及数据的加密,充分保障系统的安全性;可进行多媒体等文件的实时在线传输等,具有较好的应用前景.

九、 参考文献

[ 1]  MARCO CANTU ,罗征. Delphi 7 从入门到精通[M] . 北京:电子工业出版社,2003.

[ 2]  方军,吴晓冰,沈金龙. 中间件TCP/ IP 网络接口的实现[J ] . 网络报,1999 , (19) :33234.

[ 3]  王红霞,姚家亮. 网络环境下基于Winsock 的进程通信方法[J ] . 计算机时代,2001 , (10) :26227.

[ 4] 谢希仁.计算机网络[M].第4 版.北京:电子工业出版社,2003.100-113.

[ 5 ] 赵秀英.Delphi 网络高级编程[M].北京:人民邮电出版社?,2001.83-85.

[ 6] 申普兵,行明顺,王兆祥,等.计算机网络与通信[M].北京:人民邮电出版社,2006.9-11.

附录:课程设计中要用到的Winsock函数

WSAStartup初始化socket库

WSACleanup结束socket库的使用

socket为所要进行的网络通信建立标识符
connect连接到远程主机
closesocket结束通信,关闭标识符
bind将IP地址、TCP端口号与套接字标识符绑定

listen将接受套接字置于被动模式,

将服务器置于侦听状态,并指定允许的连接数

accept接受下一个呼入的连接
recv接收传入的TCP数据

recvfrom接收传入的UDP数据

select在指定的套接字集准备好接收数据前一直等待
send发送TCP数据

sendto发送UDP数据

shutdown释放TCP连接

getpeername从套接字中获取对等方的端口地址
setsocketopt获取当前套接字的可变选项
gethostbyname

inet_addr

把域名转换成网络IP地址

把用点分十进制表示的IP地址转换成网络IP地址

getservbyname

getprotobyname

获得服务器的端口号

把TCP、UDP转换成相应的服务号码(interger)

附:源程序代码:

void CChatRoomDlg::DlgAllInit()

{

    CheckRadioButton(IDC_RADIO_CLIENT, IDC_RADIO_SERVER, IDC_RADIO_CLIENT);

    SetDlgItemText(IDC_IP_ADDR, _T("127.0.0.1"));    //  初始化ip地址为本机地址。

    SetDlgItemText(IDC_CONNECT_PORT, _T("5566"));  //  初始化端口。

    SetDlgItemText(IDC_LISTEN_PORT, _T("5566"));

EnableWindow(IDC_STOP_CLIENT, FALSE);

    EnableWindow(IDC_LISTEN_PORT, FALSE);

    EnableWindow(IDC_STOP_SERVER, FALSE);

    EnableWindow(IDC_START_SERVER, FALSE);

    EnableWindow(IDC_STATIC_LISTEN_PORT, FALSE);     // 初始化按键启用or禁用。

    EnableWindow(IDC_SENDMSG, FALSE);

}

BOOL CChatRoomDlg::EnableWindow(UINT uID, BOOL bEnable)

{

return GetDlgItem(uID)->EnableWindow(bEnable);

}

void CChatRoomDlg::ExtendDiaog(BOOL bShow)

{

    static CRect m_DlgRectLarge(0, 0, 0, 0);

    static CRect m_DlgRectSmall(0, 0, 0, 0);

    static CRect m_GroupRectLarge(0, 0, 0, 0);

    static CRect m_GroupRectSmall(0, 0, 0, 0);         // 设置 窗口大小 

    if ( m_DlgRectLarge.IsRectNull() ) {

        GetWindowRect(&m_DlgRectLarge);

        m_DlgRectSmall = m_DlgRectLarge;

        m_DlgRectSmall.right -= 220;

::GetWindowRect(GetDlgItem(IDC_FRAME)->GetSafeHwnd(), &m_GroupRectLarge);

        m_GroupRectSmall = m_GroupRectLarge;

        m_GroupRectSmall.right -= 220;                  // 设置 窗口  伸缩大小范围

    }

    if ( bShow ) {

        bShowAll = TRUE;

        SetWindowPos(NULL, 0, 0, m_DlgRectLarge.Width(), m_DlgRectLarge.Height(), SWP_NOZORDER | SWP_NOMOVE);

        ::SetWindowPos(GetDlgItem(IDC_FRAME)->GetSafeHwnd(), NULL, 0, 0, m_GroupRectLarge.Width(), m_GroupRectLarge.Height(), SWP_NOZORDER | SWP_NOMOVE);

    }else{

        bShowAll = FALSE;

        SetWindowPos(NULL, 0, 0, m_DlgRectSmall.Width(), m_DlgRectSmall.Height(), SWP_NOZORDER | SWP_NOMOVE);

        ::SetWindowPos(GetDlgItem(IDC_FRAME)->GetSafeHwnd(), NULL, 0, 0, m_GroupRectSmall.Width(), m_GroupRectSmall.Height(), SWP_NOZORDER | SWP_NOMOVE);

    }

}

void CChatRoomDlg::OnBnClickedNetset()

{

    if ( bShowAll ) {

        ExtendDiaog(FALSE);

    }else{

        ExtendDiaog(TRUE);                         //  设置按键“网络设置”的作用

    }

}

void CChatRoomDlg::OnBnClickedStartServer()

{

    m_hListenThread = CreateThread(NULL, 0, ListenThreadFunc, this, 0, NULL);

}

void CChatRoomDlg::ShowMsg(CString strMsg)

{

    m_MsgEdit.SetSel(-1, -1);

    m_MsgEdit.ReplaceSel(strMsg+_T("\\r\\n"));

}

void CChatRoomDlg::RemoveClientFromArray(CClientItem in_Item)

{

for( int idx = 0; idx         CClientItem tItem = m_ClientArray.GetAt(idx);

        if ( tItem.m_Socket == in_Item.m_Socket &&

            tItem.hThread == in_Item.hThread &&

            tItem.m_strIp == in_Item.m_strIp ) {

                m_ClientArray.RemoveAt(idx);               

        }

    }

}

void CChatRoomDlg::OnBnClickedSendmsg()

{

    CString strMsg;

    GetDlgItemText(IDC_INPUT_MSG, strMsg);

    if ( m_bIsServer == TRUE ) {

        strMsg = _T("重庆理工大学聊天室的服务器:>") + strMsg;

        ShowMsg(strMsg);

        SendClientsMsg(strMsg);

    }else if (m_bIsServer == FALSE) {

        CString strTmp = _T("重庆理工大学聊天室的客户端:>") + strMsg;

        ShowMsg(strTmp);

        int iSend = send(m_ConnectSock, (char *)strMsg.GetBuffer(), strMsg.GetLength()*sizeof(TCHAR), 0);

        strMsg.ReleaseBuffer();

    }else{

        AfxMessageBox(_T("请您先进入聊天室!"));

    }

    SetDlgItemText(IDC_INPUT_MSG, _T(""));                    

}                                                   // socket 基本应用

void CChatRoomDlg::OnBnClickedStartClient()

{

    m_hConnectThred = CreateThread(NULL, 0, ConnectThreadFunc, this, 0, NULL);

}

void CChatRoomDlg::SendClientsMsg(CString strMsg, CClientItem *pNotSend)

{

    TCHAR szBuf[MAX_BUF_SIZE] = {0};

    _tcscpy_s(szBuf, MAX_BUF_SIZE, strMsg);

for( INT_PTR idx = 0; idx < m_ClientArray.GetCount(); idx++ ) {

        if ( !pNotSend || pNotSend->m_Socket != m_ClientArray.GetAt(idx).m_Socket || pNotSend->hThread != m_ClientArray.GetAt(idx).hThread ||

            pNotSend->m_strIp != m_ClientArray.GetAt(idx).m_strIp) {

                send(m_ClientArray.GetAt(idx).m_Socket, (char *)szBuf, _tcslen(szBuf)*sizeof(TCHAR), 0);

        }

    }

}

void CChatRoomDlg::OnEnChangeInputMsg()

{

    CString strMsg;

    GetDlgItemText(IDC_INPUT_MSG, strMsg);

    if ( strMsg.IsEmpty() ) {

        EnableWindow(IDC_SENDMSG, FALSE);

    }else{

        EnableWindow(IDC_SENDMSG);

    }

}

void CChatRoomDlg::StopClient()

{

    bShutDown = TRUE;

    DWORD dwRet = WaitForSingleObject(m_hConnectThred, 1000);

    if ( dwRet != WAIT_OBJECT_0 ) {

        TerminateThread(m_hConnectThred, -1);

        closesocket(m_ConnectSock);

    }

    m_hConnectThred = NULL;

    m_ConnectSock = INVALID_SOCKET;

    m_bIsServer = -1;

    bShutDown = FALSE;

}

void CChatRoomDlg::StopServer()

{

    UINT nCount = m_ClientArray.GetCount();

    HANDLE *m_pHandles = new HANDLE[nCount+1];

    m_pHandles[0] = m_hListenThread;

for( int idx = 0; idx < nCount; idx++ ) {

        m_pHandles[idx+1] = m_ClientArray.GetAt(idx).hThread;

    }

    bShutDown = TRUE;

    DWORD dwRet = WaitForMultipleObjects(nCount+1, m_pHandles, TRUE, 1000);

    if ( dwRet != WAIT_OBJECT_0 ) {

        for( INT_PTR i = 0; i < m_ClientArray.GetCount(); i++ ) {

            TerminateThread(m_ClientArray.GetAt(i).hThread, -1);

            closesocket(m_ClientArray.GetAt(i).m_Socket);

        }

        TerminateThread(m_hListenThread, -1);

        closesocket(m_ListenSock);

    }

    delete [] m_pHandles;

    m_hListenThread = NULL;

    m_ListenSock = INVALID_SOCKET;

    m_bIsServer = -1;

    bShutDown = FALSE;

}

void CChatRoomDlg::OnBnClickedStopClient()

{

    StopClient();

    ShowMsg(_T("停止客户端成功!"));

    EnableWindow(IDC_START_CLIENT);

    EnableWindow(IDC_STOP_CLIENT, FALSE);

}

void CChatRoomDlg::OnBnClickedStopServer()

{

    StopServer();

    ShowMsg(_T("停止服务器成功!"));

    EnableWindow(IDC_START_SERVER);

    EnableWindow(IDC_STOP_SERVER, FALSE);

}

void CChatRoomDlg::OnBnClickedRadioClient()

{

    int iRet = -1;

    if ( m_bIsServer == TRUE ) {

        int iRet = MessageBox(_T("您是聊天室的服务器端,如果您退出,所有的客户端都将掉线!\\r\\n您确定退出吗?"), _T("提示"), MB_OKCANCEL | MB_ICONWARNING);

        if ( iRet == IDOK ) {

            StopServer();

        }else{

            CheckRadioButton(IDC_RADIO_CLIENT, IDC_RADIO_SERVER, IDC_RADIO_SERVER);

        }

    }

    if ( iRet == IDOK || m_bIsServer == -1 ) {

        EnableWindow(IDC_IP_ADDR);

        EnableWindow(IDC_CONNECT_PORT);

        EnableWindow(IDC_STATIC_SERVER_IP);

        EnableWindow(IDC_STATIC_SERVER_PORT);

        EnableWindow(IDC_START_CLIENT);

        EnableWindow(IDC_STOP_CLIENT, FALSE);

        EnableWindow(IDC_LISTEN_PORT, FALSE);

        EnableWindow(IDC_STOP_SERVER, FALSE);

        EnableWindow(IDC_START_SERVER, FALSE);

        EnableWindow(IDC_STATIC_LISTEN_PORT, FALSE);

    }

}

void CChatRoomDlg::OnBnClickedRadioServer()

{

    int iRet = -1;

    if ( m_bIsServer == FALSE ) {

        int iRet = MessageBox(_T("您正在聊天室中,确定退出吗?"), _T("提示"), MB_OKCANCEL | MB_ICONWARNING);

        if ( iRet == IDOK ) {

            StopClient();

        }else{

            CheckRadioButton(IDC_RADIO_CLIENT, IDC_RADIO_SERVER, IDC_RADIO_CLIENT);

        }

    }

    if ( iRet == IDOK || m_bIsServer == -1) {

        EnableWindow(IDC_LISTEN_PORT);

        EnableWindow(IDC_STOP_SERVER, FALSE);

        EnableWindow(IDC_START_SERVER);

        EnableWindow(IDC_STATIC_LISTEN_PORT);

        EnableWindow(IDC_IP_ADDR, FALSE);

        EnableWindow(IDC_CONNECT_PORT, FALSE);

        EnableWindow(IDC_STATIC_SERVER_IP, FALSE);

        EnableWindow(IDC_STATIC_SERVER_PORT, FALSE);

        EnableWindow(IDC_START_CLIENT, FALSE);

        EnableWindow(IDC_STOP_CLIENT, FALSE);

    }

}

void CChatRoomDlg::OnBnClickedCancel()

{

    if ( m_bIsServer == TRUE ) {

        StopServer();

    }else if ( m_bIsServer == FALSE ) {

        StopClient();

    }

    OnCancel();

}

void CChatRoomDlg::OnBnClickedOther()

{

    CPoint pt;

    CRect mRect;

    CMenu mMenu, *pMenu = NULL;

GetDlgItem(IDC_OTHER)->GetWindowRect(&mRect);

    pt = mRect.BottomRight();

    pt.y = mRect.top+10;

    mMenu.LoadMenu(IDR_MENU1);

    pMenu = mMenu.GetSubMenu(0);

pMenu->TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON, pt.x, pt.y, this);

}

BOOL CChatRoomDlg::TrayMyIcon(BOOL bAdd)

{

    BOOL bRet = FALSE;

    NOTIFYICONDATA tnd;

    tnd.cbSize = sizeof(NOTIFYICONDATA);

    tnd.hWnd = GetSafeHwnd();

    tnd.uID = IDR_MAINFRAME;

    if ( bAdd == TRUE ) {

        tnd.uFlags = NIF_MESSAGE | NIF_ICON | NIF_TIP;

        tnd.uCallbackMessage = WM_TRAYICON_MSG;

        tnd.hIcon = LoadIcon(AfxGetInstanceHandle(), MAKEINTRESOURCE(IDR_MAINFRAME));

        _tcscpy_s(tnd.szTip, sizeof(tnd.szTip), _T("聊天室v1.0"));

        ShowWindow(SW_MINIMIZE);

        ShowWindow(SW_HIDE);

        bRet = Shell_NotifyIcon(NIM_ADD, &tnd);

    }else{

        ShowWindow(SW_SHOWNA);

        SetForegroundWindow();

        bRet = Shell_NotifyIcon(NIM_DELETE, &tnd);

    }

    return bRet;

}

void CChatRoomDlg::OnMenuTrayinco()

{

    TrayMyIcon();

}

LRESULT CChatRoomDlg::OnTrayCallBackMsg(WPARAM wparam, LPARAM lparam)

{

    switch(lparam)

    {

    case WM_RBUTTONUP:

        {

            CMenu mMenu, *pMenu = NULL;

            CPoint pt;

            mMenu.LoadMenu(IDR_MENU2);

            pMenu = mMenu.GetSubMenu(0);

            GetCursorPos(&pt);

            SetForegroundWindow();

            pMenu->TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON, pt.x, pt.y, this);

            break;

        }

    case WM_LBUTTONDBLCLK:

        ShowWindow(SW_RESTORE);

        SetForegroundWindow();

        TrayMyIcon(FALSE);

        break;

文档

基于Socket的即时通讯系统

评阅教师评语:课程设计成绩考勤成绩实做成绩报告成绩总评成绩指导教师签名:《综合课程设计》设计报告论文题目:基于Socket的即时通讯系统学院(系):班级:学生姓名:学号指导教师:时间:2011年6月7日到2011年6月17日一、设计题目基于Socket的即时通讯系统二、设计目的通过综合课程设计,使学生能够运用《数字信号处理》、《信号与系统》、《通信原理》、《面向对象的程序设计》、《计算机通信网》、《通信协议开发及应用》等课程的知识来设计一个基于Socket的即时通讯系统,培养学生的动手能力以及
推荐度:
  • 热门焦点

最新推荐

猜你喜欢

热门推荐

专题
Top