winCE平台聊天器的设计

刚开学找了个工作,要做嵌入式方面的,用的是winCE平台,因为之前没有用过,指导我们的大虾就让我们写一个聊天器,一个是客户端的,一个是服务端,要求使用时,有服务器开启服务,然后客户端便可以连接到服务端,连接成功后双方便可以通信聊天等,我费了一周时间才基本做了出来,给各位参考参考,里面共涉及到以下知识:

VC++语言,(这个我之前可是不会的,一直用C,区别太大了。)

多线程,(创建线程,接收数据时用,我不会用非阻塞式socket,只好创建新的线程,这个要好好看看。)

socket,(socket的创建,连接,接收,发送,断开等,挺复杂的。)

下面就给出程序,供大家参考,因为前段时间重装了系统,没有vs2008,只能上传程序,没有截图,凑活看吧。


// chat_clientDlg.cpp : 实现文件
// Edit by lineter
// QQ: 542375845

#include "stdafx.h"
#include "chat_client.h"
#include "chat_clientDlg.h"

DWORD ReciveThread(PVOID   pArg);

#ifdef _DEBUG
#define new DEBUG_NEW
#endif

// Cchat_clientDlg 对话框

Cchat_clientDlg::Cchat_clientDlg(CWnd* pParent /*=NULL*/)
	: CDialog(Cchat_clientDlg::IDD, pParent)
{
	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}

void Cchat_clientDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	DDX_Control(pDX, IDC_EDIT1, idcEdit1);
}

BEGIN_MESSAGE_MAP(Cchat_clientDlg, CDialog)
#if defined(_DEVICE_RESOLUTION_AWARE) && !defined(WIN32_PLATFORM_WFSP)
	ON_WM_SIZE()
#endif
	//}}AFX_MSG_MAP
	ON_BN_CLICKED(IDC_BUTTON1, &Cchat_clientDlg::OnBnClickedButton1)
	ON_BN_CLICKED(IDC_BUTTON2, &Cchat_clientDlg::OnBnClickedButton2)
	ON_BN_CLICKED(IDC_BUTTON3, &Cchat_clientDlg::OnBnClickedButton3)
	ON_EN_CHANGE(IDC_EDIT2, &Cchat_clientDlg::OnEnChangeEdit2)
	ON_BN_CLICKED(IDC_BUTTON4, &Cchat_clientDlg::OnBnClickedButton4)
END_MESSAGE_MAP()


// 接收线程
DWORD ReciveThread(PVOID   pArg)
{
	// TODO: 在此添加控件通知处理程序代码
	Cchat_clientDlg *p=(Cchat_clientDlg *)pArg;

	CString csContent;	//	接收到的数据

	int recv_no=0;
	char cRecvBuf[100];

	while(1)
	{
		// 清空字符串
		memset(cRecvBuf,0,sizeof(cRecvBuf));
		// 接收数据
		recv_no=recv(p->sockClient,cRecvBuf,100,0);		
		// 处理接收到的数据
		csContent.Empty();
		csContent.Append((CString)cRecvBuf);
		csContent.Insert(0,CString("Server:"));
		csContent.Append(CString("\r\n"));
		// 调用类中显示数据的函数
		p->DispRecive(csContent);
		Sleep(1000);
	}
	return 0;
}

// 显示接收到的内容
void Cchat_clientDlg::DispRecive(CString csContent)
{
	CString csAllcontent;
	// 得到文本框内容,并将数据加上顶端显示
	GetDlgItemText(IDC_EDIT1,csAllcontent);
	SetDlgItemText(IDC_EDIT1,csContent+csAllcontent);

}

// Cchat_clientDlg 消息处理程序

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

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

	// 显示默认服务器ip
	CString csContent;
	csContent="";
	csContent.Append(CString("192.168.3.73"));
	SetDlgItemText(IDC_EDIT3,csContent);

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

#if defined(_DEVICE_RESOLUTION_AWARE) && !defined(WIN32_PLATFORM_WFSP)
void Cchat_clientDlg::OnSize(UINT /*nType*/, int /*cx*/, int /*cy*/)
{
	if (AfxIsDRAEnabled())
	{
		DRA::RelayoutDialog(
			AfxGetResourceHandle(), 
			this->m_hWnd, 
			DRA::GetDisplayMode() != DRA::Portrait ? 
			MAKEINTRESOURCE(IDD_CHAT_CLIENT_DIALOG_WIDE) : 
			MAKEINTRESOURCE(IDD_CHAT_CLIENT_DIALOG));
	}
}
#endif


void Cchat_clientDlg::OnEnChangeEditIp()
{
	// TODO:  如果该控件是 RICHEDIT 控件,则它将不会
	// 发送该通知,除非重写 CDialog::OnInitDialog()
	// 函数并调用 CRichEditCtrl().SetEventMask(),
	// 同时将 ENM_CHANGE 标志“或”运算到掩码中。

	// TODO:  在此添加控件通知处理程序代码

}

void Cchat_clientDlg::OnEnChangeEditPort()
{
	// TODO:  如果该控件是 RICHEDIT 控件,则它将不会
	// 发送该通知,除非重写 CDialog::OnInitDialog()
	// 函数并调用 CRichEditCtrl().SetEventMask(),
	// 同时将 ENM_CHANGE 标志“或”运算到掩码中。

	// TODO:  在此添加控件通知处理程序代码
}

// 发送内容
void Cchat_clientDlg::OnBnClickedButton1()
{
	CString csContent;
	char cRecvBuf[100];
	CString csAllcontent;
	char cAllcontent[500];
	
	csContent = "";
	memset(cRecvBuf,0,sizeof(cRecvBuf));
	memset(cAllcontent,0,sizeof(cAllcontent));

	// 得到输入内容并发送
	GetDlgItemText(IDC_EDIT2,csContent);
	WCharToMByte(csContent,(LPSTR)cRecvBuf,sizeof(cRecvBuf)/sizeof(cRecvBuf[0]));
	send(sockClient,cRecvBuf,strlen(cRecvBuf)+1,0);

	// 将输入内容处理后显示
	csContent.Insert(0,CString("Client:"));
	csContent.Append(CString("\r\n"));
	DispRecive(csContent);
	
}

// 关闭连接
void Cchat_clientDlg::OnBnClickedButton2()
{
	// TODO: 在此添加控件通知处理程序代码


	DWORD ExitCode;	// 线程退出码

	// 得到线程退出码
	GetExitCodeThread(handle1,&ExitCode);
	// 通过线程退出码结束线程
	TerminateThread(handle1,ExitCode);
	// 关闭线程句柄
	CloseHandle(handle1); 
	handle1=NULL;

	// 关闭socket
	closesocket(sockClient);
	WSACleanup();

	// 显示断开信息
	CString csCancel;
	csCancel.Append(CString("Disconnected !"));
	SetDlgItemText(IDC_EDIT2,csCancel);
	
	// 更改控件属性
	GetDlgItem(IDC_BUTTON1)-> EnableWindow(FALSE);
	GetDlgItem(IDC_BUTTON2)-> EnableWindow(FALSE);
	GetDlgItem(IDC_BUTTON4)-> EnableWindow(FALSE);
	GetDlgItem(IDC_BUTTON3)-> EnableWindow(TRUE);

}

// 建立连接
void Cchat_clientDlg::OnBnClickedButton3()
{
	// TODO: 在此添加控件通知处理程序代码
	CString csContent;			//	输入框中内容,即IP地址(CString 类型)
	char cIP[100];				//	输入框中内容,即IP地址(char    类型)
	
	csContent.Empty();			//	清空原始内容
	memset(cIP,0,sizeof(cIP));	//	清空字符串
	//	得到输入框中内容并转换为char型
	GetDlgItemText(IDC_EDIT3,csContent);
	WCharToMByte(csContent,(LPSTR)cIP,sizeof(cIP)/sizeof(cIP[0]));

	// 创建socket,客服端
	wVersionRequested = MAKEWORD( 1, 1 );
	err = WSAStartup( wVersionRequested, &wsaData );
	if ( err != 0 )
	{
		AfxMessageBox(CString("WSAStartup error"),0,0);
		return;
	}
	if ( LOBYTE( wsaData.wVersion ) != 1 ||
	        HIBYTE( wsaData.wVersion ) != 1 )
	{
		AfxMessageBox(CString("LOBYTE error"),0,0);
		WSACleanup( );
		AfxMessageBox(CString("LOBYTE OK error"),0,0);
		return;
	}
	sockClient=socket(AF_INET,SOCK_STREAM,0);	// 客户端socket

	// 通过ip地址和端口和服务器连接
	SOCKADDR_IN addrSrv;
	addrSrv.sin_addr.S_un.S_addr=inet_addr(cIP);
	//addrSrv.sin_addr.S_un.S_addr=inet_addr("192.168.3.73");
	addrSrv.sin_family=AF_INET;
	addrSrv.sin_port=htons(1000);
	connect(sockClient,(SOCKADDR*)&addrSrv,sizeof(SOCKADDR));

	// 显示连接成功信息
	CString csOk;
	csOk.Append(CString("Connected !"));
	SetDlgItemText(IDC_EDIT2,csOk);

	// 修改控件属性
	GetDlgItem(IDC_BUTTON1)-> EnableWindow(TRUE);
	GetDlgItem(IDC_BUTTON2)-> EnableWindow(TRUE);
	GetDlgItem(IDC_BUTTON4)-> EnableWindow(TRUE);
	GetDlgItem(IDC_BUTTON3)-> EnableWindow(FALSE);

	// 创建接收数据进程
	handle1=CreateThread(NULL,0,ReciveThread,this,0,NULL);

}

void Cchat_clientDlg::OnEnChangeEdit2()
{
	// TODO:  如果该控件是 RICHEDIT 控件,则它将不会
	// 发送该通知,除非重写 CDialog::OnInitDialog()
	// 函数并调用 CRichEditCtrl().SetEventMask(),
	// 同时将 ENM_CHANGE 标志“或”运算到掩码中。

	// TODO:  在此添加控件通知处理程序代码
}

// CString转char 函数
BOOL Cchat_clientDlg::WCharToMByte(LPCWSTR lpcwszStr, LPSTR lpszStr, DWORD dwSize)
{
	DWORD dwMinSize;
	dwMinSize = WideCharToMultiByte(CP_OEMCP,NULL,lpcwszStr,-1,NULL,0,NULL,FALSE);
	if(dwSize+1 < dwMinSize)
	{
		return FALSE;
	}
	WideCharToMultiByte(CP_OEMCP,NULL,lpcwszStr,-1,lpszStr,dwSize,NULL,FALSE);
	return TRUE;
}

// 按键接收函数。警告:按下后将卡死至接收到数据
void Cchat_clientDlg::OnBnClickedButton4()
{
	// TODO: 在此添加控件通知处理程序代码

	CString csContent;
	CString csAllcontent;

	int recv_no=0;
	char cRecvBuf[100];
	// 通过socket接收数据,阻塞式
	recv_no=recv(sockClient,cRecvBuf,100,0);

	// 将接收到的数据处理后放入输入框顶端
	csContent.Empty();
	csContent.Append((CString)cRecvBuf);
	csContent.Insert(0,CString("Server:"));
	csContent.Append(CString("\r\n"));
	DispRecive(csContent);
}

共有两个文本编辑框,4个按键,对应的头文件也有相应更改如下


// chat_clientDlg.h : 头文件
//

#pragma once


#include <Winsock2.h>
#pragma comment(lib, "Ws2.lib")
#include <stdio.h>
#include "afxwin.h"

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

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

	WORD wVersionRequested;
	WSADATA wsaData;
	int err;
	SOCKET sockClient,sockSrv;
	BOOL WCharToMByte(LPCWSTR lpcwszStr, LPSTR lpszStr, DWORD dwSize);
	DWORD WINAPI revThread(LPVOID lpParameter);
	void DispRecive(CString csContent);		//显示接收到的数据
	HANDLE   handle1;	//	进程的句柄

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

// 实现
protected:
	HICON m_hIcon;

	// 生成的消息映射函数
	virtual BOOL OnInitDialog();
#if defined(_DEVICE_RESOLUTION_AWARE) && !defined(WIN32_PLATFORM_WFSP)
	afx_msg void OnSize(UINT /*nType*/, int /*cx*/, int /*cy*/);
#endif
	DECLARE_MESSAGE_MAP()
public:
	afx_msg void OnEnChangeEdit1();
	afx_msg void OnEnChangeEditIp();
	afx_msg void OnEnChangeEditPort();
	afx_msg void OnBnClickedButton1();
	afx_msg void OnBnClickedButton2();
	afx_msg void OnBnClickedButton3();
	afx_msg void OnEnChangeEdit2();
	afx_msg void OnBnClickedButton4();
	CEdit idcEdit1;
};

以上是客户端,还有服务端,和客户端很像,但也有一些不同。


// chat_serverDlg.cpp : 实现文件
//

#include "stdafx.h"
#include "chat_server.h"
#include "chat_serverDlg.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#endif

DWORD ReciveThread(PVOID   pArg);

// CString转char 函数
BOOL Cchat_serverDlg::WCharToMByte(LPCWSTR lpcwszStr, LPSTR lpszStr, DWORD dwSize)
{
	DWORD dwMinSize;
	dwMinSize = WideCharToMultiByte(CP_OEMCP,NULL,lpcwszStr,-1,NULL,0,NULL,FALSE);
	if(dwSize+1 < dwMinSize)
	{
		return FALSE;
	}
	WideCharToMultiByte(CP_OEMCP,NULL,lpcwszStr,-1,lpszStr,dwSize,NULL,FALSE);
	return TRUE;
}

// 接收线程
DWORD ReciveThread(PVOID   pArg)
{
	// TODO: 在此添加控件通知处理程序代码
	Cchat_serverDlg *p=(Cchat_serverDlg *)pArg;

	int recv_no=0;
	char cRecvBuf[100];
	CString csContent;

	SOCKADDR_IN addrClient;
	int len=sizeof(SOCKADDR);
	memset(cRecvBuf,0,sizeof(cRecvBuf));
	p->sockConn=accept(p->sockSrv,(SOCKADDR*)&addrClient,&len);
	p->DispInfo(CString("one connected."));
	p->EnableSend(TRUE);
	
	while(1)
	{
		recv(p->sockConn,cRecvBuf,100,0);
		csContent.Empty();
		csContent.Append((CString)cRecvBuf);
		csContent.Insert(0,CString("Server:"));
		csContent.Append(CString("\r\n"));
		if(cRecvBuf[0]!=0)
		{
			p->DispRecive(csContent);
		}
		else
		{
			p->EnableSend(FALSE);
			closesocket(p->sockConn);
			p->DispInfo(CString("one disconnected."));
			p->sockConn=accept(p->sockSrv,(SOCKADDR*)&addrClient,&len);
			p->DispInfo(CString("one connected."));
			p->EnableSend(TRUE);
		}
	}
	return 0;
}

// 是否使能发送框
void Cchat_serverDlg::EnableSend(BOOL enable_send)
{
	if(enable_send)
	{
		GetDlgItem(IDC_BUTTON1)-> EnableWindow(TRUE);
	}
	else
	{
		GetDlgItem(IDC_BUTTON1)-> EnableWindow(FALSE);
	}
}

// 将数据显示在文本框之上
void Cchat_serverDlg::DispRecive(CString csContent)
{
	CString csAllcontent;

	GetDlgItemText(IDC_EDIT1,csAllcontent);
	SetDlgItemText(IDC_EDIT1,csContent+csAllcontent);

}
// 显示提示信息
void Cchat_serverDlg::DispInfo(CString csContent)
{
	SetDlgItemText(IDC_EDIT2,csContent);

}

Cchat_serverDlg::Cchat_serverDlg(CWnd* pParent /*=NULL*/)
	: CDialog(Cchat_serverDlg::IDD, pParent)
{
	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}

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

BEGIN_MESSAGE_MAP(Cchat_serverDlg, CDialog)
#if defined(_DEVICE_RESOLUTION_AWARE) && !defined(WIN32_PLATFORM_WFSP)
	ON_WM_SIZE()
#endif
	//}}AFX_MSG_MAP
	ON_BN_CLICKED(IDC_BUTTON3, &Cchat_serverDlg::OnBnClickedButton3)
	ON_BN_CLICKED(IDC_BUTTON2, &Cchat_serverDlg::OnBnClickedButton2)
	ON_BN_CLICKED(IDC_BUTTON1, &Cchat_serverDlg::OnBnClickedButton1)
END_MESSAGE_MAP()


// Cchat_serverDlg 消息处理程序

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

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

	// TODO: 在此添加额外的初始化代码
	
	return TRUE;  // 除非将焦点设置到控件,否则返回 TRUE
}

#if defined(_DEVICE_RESOLUTION_AWARE) && !defined(WIN32_PLATFORM_WFSP)
void Cchat_serverDlg::OnSize(UINT /*nType*/, int /*cx*/, int /*cy*/)
{
	if (AfxIsDRAEnabled())
	{
		DRA::RelayoutDialog(
			AfxGetResourceHandle(), 
			this->m_hWnd, 
			DRA::GetDisplayMode() != DRA::Portrait ? 
			MAKEINTRESOURCE(IDD_CHAT_SERVER_DIALOG_WIDE) : 
			MAKEINTRESOURCE(IDD_CHAT_SERVER_DIALOG));
	}
}
#endif

void Cchat_serverDlg::OnBnClickedButton3()
{
	// TODO: 在此添加控件通知处理程序代码

	WORD wVersionRequested;
	WSADATA wsaData;
	int err;

	wVersionRequested = MAKEWORD( 1, 1 );

	err = WSAStartup( wVersionRequested, &wsaData );
	if ( err != 0 )
	{
		return;
	}


	if ( LOBYTE( wsaData.wVersion ) != 1 ||
	        HIBYTE( wsaData.wVersion ) != 1 )
	{
		WSACleanup( );
		return;
	}
	sockSrv=socket(AF_INET,SOCK_STREAM,0);

	SOCKADDR_IN addrSrv;
	addrSrv.sin_addr.S_un.S_addr=htonl(INADDR_ANY);
	addrSrv.sin_family=AF_INET;
	addrSrv.sin_port=htons(1000);

	bind(sockSrv,(SOCKADDR*)&addrSrv,sizeof(SOCKADDR));

	listen(sockSrv,5);
	handle1=CreateThread(NULL,0,ReciveThread,this,0,NULL);

	GetDlgItem(IDC_BUTTON1)-> EnableWindow(FALSE);
	GetDlgItem(IDC_BUTTON2)-> EnableWindow(TRUE);
	GetDlgItem(IDC_BUTTON3)-> EnableWindow(FALSE);

	DispInfo(CString("Server start!"));
}

void Cchat_serverDlg::OnBnClickedButton2()
{
	// TODO: 在此添加控件通知处理程序代码

	DWORD ExitCode;	// 线程退出码

	// 得到线程退出码
	GetExitCodeThread(handle1,&ExitCode);
	// 通过线程退出码结束线程
	TerminateThread(handle1,ExitCode);
	// 关闭线程句柄
	CloseHandle(handle1); 
	handle1=NULL;

	// 关闭socket
	closesocket(sockSrv);
	WSACleanup();
	
	// 更改控件属性
	GetDlgItem(IDC_BUTTON1)-> EnableWindow(FALSE);
	GetDlgItem(IDC_BUTTON2)-> EnableWindow(FALSE);
	GetDlgItem(IDC_BUTTON3)-> EnableWindow(TRUE);
	// 显示断开信息
	DispInfo(CString("Server closed!"));
}

void Cchat_serverDlg::OnBnClickedButton1()
{
	CString csContent;
	char cRecvBuf[100];
	CString csAllcontent;
	char cAllcontent[500];
	
// chat_serverDlg.h : 头文件
//

#pragma once

#include <Winsock2.h>
#pragma comment(lib, "Ws2.lib")
#include <stdio.h>
#include "afxwin.h"

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

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

/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
	SOCKET sockSrv;
	SOCKET sockConn;
	void DispRecive(CString csContent);		//显示接收到的数据
	HANDLE   handle1;	//	进程的句柄
	BOOL WCharToMByte(LPCWSTR lpcwszStr, LPSTR lpszStr, DWORD dwSize);
	void Cchat_serverDlg::DispInfo(CString csContent);	//	显示信息
	void EnableSend(BOOL enable_send);					// 是否使能发送键

/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/

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

// 实现
protected:
	HICON m_hIcon;

	// 生成的消息映射函数
	virtual BOOL OnInitDialog();
#if defined(_DEVICE_RESOLUTION_AWARE) && !defined(WIN32_PLATFORM_WFSP)
	afx_msg void OnSize(UINT /*nType*/, int /*cx*/, int /*cy*/);
#endif
	DECLARE_MESSAGE_MAP()
public:
	afx_msg void OnBnClickedButton3();
	afx_msg void OnBnClickedButton2();
	afx_msg void OnBnClickedButton1();
};

int len=sizeof(SOCKADDR);csContent = "";memset(cRecvBuf,0,sizeof(cRecvBuf));memset(cAllcontent,0,sizeof(cAllcontent));// 得到输入内容并发送GetDlgItemText(IDC_EDIT2,csContent);WCharToMByte(csContent,(LPSTR)cRecvBuf,sizeof(cRecvBuf)/sizeof(cRecvBuf[0]));send(sockConn,cRecvBuf,strlen(cRecvBuf)+1,0);// 将输入内容处理后显示csContent.Insert(0,CString("Client:"));csContent.Append(CString("\r\n"));DispRecive(csContent);}





以上就是全部代码,有需要源文件的可以直接留言,告诉我邮箱,我会尽快发送给各位。


  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 10
    评论
评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值