程式架構與寫法介紹:b92043/homework/檔案...網際網路電話系統作業一程式說明文件...
TRANSCRIPT
-
網際網路電話系統作業一程式說明文件
資工四 B92902043 徐瑞澤
程式架構與寫法介紹:
助教您好,這次的作業我按照投影片上的說明在 SimpRTPDlg.cpp 中的CSimRTPDlg 程序加入 cclRTPStartup(2)以初始化 RTP 的物件並設定最大 channel數為 2,接著由於我有做使用者可以指定 port 的功能,所以 RTPOpenPort()這邊先不做,等到設定 peeraddress 的時候會再執行。 接著在 OnOK 程序中利用以下程式碼: m_WaveIOObj->wavInClose();
m_WaveIOObj->wavOutClose(); 把 WavIO 關閉,然後我加入以下的程式碼處理使用者自訂的 port:
for (i=0; i
-
其中 newport 是我在 SimRTPDlg.cpp 檔案開頭自訂的一個 Global Variable,目的
是儲存使用者自訂的 Port,接著執行 RTPPeerConnect(IP, newport)。
另外為了達到使用者自訂 Port 的功能,我修改了 cclRtp.c 檔案,其中 cclRTPOpen
修改如下:
RETCODE cclRTPOpen(int channel, int rtpPacketSiz, int port)
{
if( channel=MAX_RTP_CHANS )
return -1;
if( rtp[channel] ) {
RTP_PACKET_SIZ[channel] = rtpPacketSiz;
return 1;
}
rtp[channel] = rtp_open(port,0);
if( !rtp[channel] )
return -1;
rtcp[channel] = rtcp_open(port+1,0);
if( !rtcp[channel] )
return -1;
return 0;
}
我在這個函數的參數列尾端新增了一個 port 的變數,以記錄使用者自訂的 Port
Number,另外在執行 rtp_open()與 rtcp_open()的地方,將第一個參數換成 port 與
port+1,這樣 Local 端的 port 才可以設成使用者自訂的 Port。
程式功能與操作方法:
如上,使用者輸入對方電腦的 IP 位址,對方也輸入自己電腦的 IP 位址,就會使用
預設的 Port9000 連線,如果輸入對方電腦的 IP 位址之後加一個冒號,後面接上欲使用
的 Port 號碼,對方也輸入自己電腦的 IP 位址加上 Port 號碼,就可以使用指定的 Port
傳輸資料,如下是使用 port9500 做傳輸,圖示如下:
-
SimRTPDlg.cpp Source Code:
// SimRTPDlg.cpp : implementation file
//
#include "stdafx.h"
#include "SimRTP.h"
#include "SimRTPDlg.h"
#include "cclRtp.c"
//#include "WavInOut.cpp"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
char IP[100];
int newport = 9000;
///////////////////////////////////////////////////////////////////////////
//
// CAboutDlg dialog used for App About
class CAboutDlg : public CDialog
{
public:
CAboutDlg();
// Dialog Data
//{{AFX_DATA(CAboutDlg)
enum { IDD = IDD_ABOUTBOX };
-
//}}AFX_DATA
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CAboutDlg)
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
//}}AFX_VIRTUAL
// Implementation
protected:
//{{AFX_MSG(CAboutDlg)
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};
CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
{
//{{AFX_DATA_INIT(CAboutDlg)
//}}AFX_DATA_INIT
}
void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CAboutDlg)
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
//{{AFX_MSG_MAP(CAboutDlg)
// No message handlers
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
///////////////////////////////////////////////////////////////////////////
//
// CSimRTPDlg dialog
-
static CSimRTPDlg* csimrtpdlg = NULL;
CSimRTPDlg::CSimRTPDlg(CWnd* pParent /*=NULL*/)
: CDialog(CSimRTPDlg::IDD, pParent)
{
//{{AFX_DATA_INIT(CSimRTPDlg)
csimrtpdlg = this;
//}}AFX_DATA_INIT
// Note that LoadIcon does not require a subsequent DestroyIcon in Win32
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
//-----------------------------------
//cclRTPStartup add here
cclRTPStartup(2);
//-----------------------------------
m_RtpChan=0;
m_BufRTP2IO=adtBufferNew(4096);
m_BufIO2RTP=adtBufferNew(4096);
m_WaveIOObj = WavInOut::instance();
m_WaveIOObj->init(Wav2RTP,RTP2Wav);
//-----------------------------------
//RTPOpenPort add here
//RTPOpenPort();
//-----------------------------------
m_bUDP=TRUE;
m_bTCP=FALSE;
m_bCallAuto=TRUE;
m_flag = TRUE;
}
void CSimRTPDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CSimRTPDlg)
DDX_Control(pDX, IDOK, m_OK);
-
DDX_Control(pDX, IDC_EDIT1, m_IP_CTL);
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CSimRTPDlg, CDialog)
//{{AFX_MSG_MAP(CSimRTPDlg)
ON_WM_SYSCOMMAND()
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
ON_EN_CHANGE(IDC_EDIT1, OnChangeEdit1)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
///////////////////////////////////////////////////////////////////////////
//
// CSimRTPDlg message handlers
BOOL CSimRTPDlg::OnInitDialog()
{
CDialog::OnInitDialog();
// Add "About..." menu item to system menu.
// IDM_ABOUTBOX must be in the system command range.
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);
}
-
}
// Set the icon for this dialog. The framework does this automatically
// when the application's main window is not a dialog
SetIcon(m_hIcon, TRUE); // Set big icon
SetIcon(m_hIcon, FALSE); // Set small icon
// TODO: Add extra initialization here
m_IP_CTL.SetFocus();
return TRUE; // return TRUE unless you set the focus to a control
}
void CSimRTPDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
if ((nID & 0xFFF0) == IDM_ABOUTBOX)
{
CAboutDlg dlgAbout;
dlgAbout.DoModal();
}
else
{
CDialog::OnSysCommand(nID, lParam);
}
}
// If you add a minimize button to your dialog, you will need the code below
// to draw the icon. For MFC applications using the document/view model,
// this is automatically done for you by the framework.
void CSimRTPDlg::OnPaint()
{
if (IsIconic())
{
CPaintDC dc(this); // device context for painting
SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);
// Center icon in client rectangle
-
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;
// Draw the icon
dc.DrawIcon(x, y, m_hIcon);
}
else
{
CDialog::OnPaint();
}
}
// The system calls this to obtain the cursor to display while the user drags
// the minimized window.
HCURSOR CSimRTPDlg::OnQueryDragIcon()
{
return (HCURSOR) m_hIcon;
}
void CSimRTPDlg::OnCancel()
{
// TODO: Add extra cleanup here
m_WaveIOObj->stopPlaying();
m_WaveIOObj->stopRecording();
if(m_WaveIOObj->isWavInOpen) m_WaveIOObj->wavInClose();
if(m_WaveIOObj->isWavOutOpen) m_WaveIOObj->wavOutClose();
CDialog::OnCancel();
}
void CSimRTPDlg::OnChangeEdit1()
{
// TODO: If this is a RICHEDIT control, the control will not
-
// send this notification unless you override the CDialog::OnInitDialog()
// function and call CRichEditCtrl().SetEventMask()
// with the ENM_CHANGE flag ORed into the mask.
// TODO: Add your control notification handler code here
}
void CSimRTPDlg::OnOK()
{
//User specified port stored here
char assign_port[10];
int i, j;
int flag = 0;
int m;
//-----------------------------------
// TODO: Add extra validation here
m_WaveIOObj->wavInClose();
m_WaveIOObj->wavOutClose();
//-----------------------------------
//CDialog::OnOK();
int t;
t = m_IP_CTL.GetWindowText(IP, 100);
for (i=0; i
-
m = i;
j = 0;
i += 1;
while(IP[i] != '\0') {
assign_port[j] = IP[i];
i += 1;
j += 1;
}
newport = atoi(assign_port);
for(i=m; istopPlaying();
m_WaveIOObj->stopRecording();
if(m_WaveIOObj->isWavInOpen) m_WaveIOObj->wavInClose();
if(m_WaveIOObj->isWavOutOpen) m_WaveIOObj->wavOutClose();
if( TRUE == m_flag ) {
m_flag = FALSE;
m_OK.SetWindowText("掛斷");
//-----------------------------------
//RTPPeerConnect add here, assign target ip and port here.
RTPPeerConnect(IP, newport);
-
//-----------------------------------
adtBufferClear(m_BufRTP2IO);
adtBufferClear(m_BufIO2RTP);
if(m_WaveIOObj->wavInOpen(wavetype,8,8000,1,30)!=0)
m_IP_CTL.SetWindowText("Open WaveIO Error!");
else if ( m_WaveIOObj->startRecording()!=0 )
m_IP_CTL.SetWindowText("Record Error!");
if(m_WaveIOObj->wavOutOpen(wavetype,8,8000,1,30)!=0)
m_IP_CTL.SetWindowText("Open WaveOut Error!");
else if ( m_WaveIOObj->startPlaying()!=0 )
m_IP_CTL.SetWindowText("Playing Error!");
}
else {
m_flag = TRUE;
m_OK.SetWindowText("連線");
}
}
int CSimRTPDlg::RTPEventHandler(int channel,const char* buffer,int buflen)
{
return adtBufferWrite(csimrtpdlg->m_BufRTP2IO,((char *) buffer),buflen);
}
int CSimRTPDlg::Wav2RTP(char* buff, int len)
{
char buffer[1024];
int xlen=0;
memcpy(buffer,buff,len);
xlen = cclRTPWrite(csimrtpdlg->m_RtpChan,buffer,len);
return (xlen>=len)?len:xlen;
}
int CSimRTPDlg::RTP2Wav(char* buff, int len)
{
return adtBufferRead(csimrtpdlg->m_BufRTP2IO,buff,len);
-
}
int CSimRTPDlg::MediaConnection()
{
return 0;
}
int CSimRTPDlg::MediaPlayTone()
{
return 0;
}
int CSimRTPDlg::Media_RTP_Stop()
{
m_WaveIOObj->stopPlaying();
m_WaveIOObj->stopRecording();
adtBufferClear(m_BufRTP2IO);
adtBufferClear(m_BufIO2RTP);
if(m_WaveIOObj->isWavInOpen) m_WaveIOObj->wavInClose();
if(m_WaveIOObj->isWavOutOpen) m_WaveIOObj->wavOutClose();
cclRTPClose(m_RtpChan);
adtBufferClear(m_BufRTP2IO);
adtBufferClear(m_BufIO2RTP);
return 0;
}
int CSimRTPDlg::RTPOpenPort()
{
int result=0;
result=cclRTPOpen(m_RtpChan, 240, newport); /*240 = packet size */
return result;
}
-
int CSimRTPDlg::RTPPeerConnect(CString ip,int port) int CSimRTPDlg::RTPPeerConnect(CString ip,int port)
{ {
CString buf; CString buf;
buf.Format("[RTP] Open Peer RTP: IP(%s),Port(%d)\n",ip,port); buf.Format("[RTP] Open Peer RTP: IP(%s),Port(%d)\n",ip,port);
RTPOpenPort(); RTPOpenPort();
cclRTPSetPeerAddr(m_RtpChan,(LPSTR)(LPCSTR)ip,port); cclRTPSetPeerAddr(m_RtpChan,(LPSTR)(LPCSTR)ip,port);
buf.Format("[RTP] Get had open RTP listen Port
(%d)\n",cclRTPGetPort(m_RtpChan));
buf.Format("[RTP] Get had open RTP listen Port
(%d)\n",cclRTPGetPort(m_RtpChan));
cclRTPSetEventHandler(RTPEventHandler); /*set event handler */ cclRTPSetEventHandler(RTPEventHandler); /*set event handler */
return 0; return 0;
} }
RTP封包:
-
RTCP 封包:
查看程式碼(rtcp.c)的內容與 Ethereal 實際擷取的結果,此程式似乎並無傳送
RTCP 封包,所以只有附上 RTCP 的規格圖如下。