1. 程式人生 > >MFC實現簡單的聊天功能

MFC實現簡單的聊天功能

設計目標:

2.設計二  簡單的即時通訊軟體(6學時實驗)

目的與要求: 利用WinSock進行點對點通訊,工作機制模仿即時通訊軟體的基本功能,登陸,上線,傳遞資訊等等。分為客戶部分和伺服器部分兩塊,客戶部分類似一般通訊軟體例如QQ,伺服器部分主要提供客戶端使用者基本資料配置。

服務端程式碼:

#include <WinSock2.h>
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h> 
#include <string>
#include <sstream>
#pragma comment(lib,"pthreadVC2.lib")
#pragma comment(lib,"ws2_32.lib")
#include<iostream>
using namespace std;
/*void* recv1(SOCKET sockConn)
{  char recvBuf[10000];
memset(recvBuf, 0, sizeof(recvBuf));
//接收資料
while(true){

int nRecv = ::recv(sockConn, recvBuf, sizeof(recvBuf), 0);
cout<<endl;
if(nRecv>0)cout<<"他說:"<<recvBuf<<endl;
else break;}
}*/
SOCKET sockConn[10];
char password[] = "123456";	
int pass = 0;
const int nl = 100;
string user[nl] = { "123","456","789","張三" };
string pw[nl] = { "111","456","789","張三" };
int online[nl] = {0,0,0};//判斷是否線上的陣列
int match[nl] = {-1,-1,-1};//表示第i個使用者名稱匹配的是第幾個套接字
int find(string a[], string b)
{
	bool exist = false;
	for (int j = 0; j<nl; j++)
	{
		if (a[j] == b)
		{
			exist = true;
			return j;
		}
	}
	if (!exist)
		return -1;
}
int find1(SOCKET sock)
{
	for (int i = 0; i < 10; i++)
	{
		if (sock == sockConn[i])
		{
			return i;
			break;
            
		}
	}
	return -1;
}
int finds(string s)//根據使用者名稱找到對應的套接字
{
	int index = find(user,s);
	if (index >= 0)
		return match[index];
	else
		return -1;
}
int  findu(SOCKET sock )//根據套接字找使用者名稱在陣列中的位置
{
	int index = find1(sock);
	for (int i = 0; i < nl; i++)
	{
		if (match[i] == index)
			return i;
	}
	return -1;
}
int nul_index(string a[])//查詢string陣列的空位,以便於使用者註冊的插入
{
	for (int i = 0; i < nl; i++)
	{
		if (a[i].empty())
			return i;
	}
	return nl;//沒有空位,註冊已滿
}
void* recv1(void* args)
{
	char recvBuf[10000];
	char users[1000];
	char pws[1000];
	//接收資料
	bool success = false;//判斷是否登入成功 
	int id1 = (unsigned int)pthread_getw32threadid_np(pthread_self()) / 2;
	SOCKET sockConn1 = *((SOCKET*)args);//建立套接字
	memset(recvBuf, 0, sizeof(recvBuf));
	int rel = 0;
	rel = recv(sockConn1, recvBuf, sizeof(recvBuf), 0);
	if (rel<0)
		cout << "接受失敗\n";
	cout << rel<<" "<<recvBuf<<endl;
	send(sockConn1, "ack", sizeof(recvBuf),0);
	//cout<<recvBuf<<endl;
	if (strcmp(recvBuf, "1") == 0)//客戶端選擇登入 
	{
		cout << "選擇登入服務\n";
		memset(users, 0, sizeof(users));
		rel = recv(sockConn1, users, sizeof(users), 0);
		if (rel<0)//接受使用者名稱 
			cout << "recv failed";
		cout <<rel<<" "<< users << endl;
		send(sockConn1, "ack", sizeof(recvBuf),0);
		int index = find(user, users);//判斷能否找到使用者名稱 
		int sockNum = find1(sockConn1);
		if (index != -1)//找到使用者名稱      
		{
			if (online[index] == 0)
			{

				cout << "找到使用者名稱" << endl;
				memset(pws, 0, sizeof(pws));
				if (recv(sockConn1, pws, sizeof(pws), 0) < 0)//接受密碼 
					cout << "recv failed";
				cout << pws << endl;
				if (pws == pw[index])//密碼正確 
				{   
					online[index] = 1;
					success = true;
					match[index] = sockNum;
					if (send(sockConn1, "密碼正確", sizeof(recvBuf), 0) < 0)
					{
						cout << "傳送失敗";
					}
				}
				else//密碼錯誤 
				{
					send(sockConn1, "密碼錯誤", sizeof(recvBuf), 0);
				}
			}
			else 
			{
				memset(pws, 0, sizeof(pws));
				if (recv(sockConn1, pws, sizeof(pws), 0)<0)//接受密碼 
					cout << "recv failed";
				if (send(sockConn1, "該使用者已存在", sizeof(recvBuf), 0)<0)
					cout << "傳送失敗";
			}
		}
		if (index == -1)//未找到使用者名稱 
		{
			memset(pws, 0, sizeof(pws));
			if (recv(sockConn1, pws, sizeof(pws), 0)<0)//接受密碼 
				cout << "recv failed";
			if (send(sockConn1, "使用者名稱不存在", sizeof(recvBuf), 0)<0)
					cout << "傳送失敗";
		}
		if (success)
		{
			char buf[1000];
			int id = find1(sockConn1);
			int n = findu(sockConn1);
			const char*p=user[n].data();
			//user[n].copy(p, 40, 0);//這裡5,代表複製幾個字元,0代表複製的位置  
			//*(p + 40) = '\0';//要手動加上結束符

			if (id >= 1)
			{
				for (int j = 1; j < id + 1; j++)//好友上線功能 
				{

					if (send(sockConn[j - 1], p, sizeof(p), 0) < 0) //,sizeof(buf),0)<0)
						cout << "send failed";
					if (send(sockConn[j - 1], "已上線", sizeof(buf), 0) < 0)
						cout << "send failed";
				}
			}
			while (true)
			{
				memset(recvBuf, 0, sizeof(recvBuf));
				recv(sockConn1,recvBuf,sizeof(recvBuf),0);//接受要傳送的使用者名稱
				int index = find(user,recvBuf);//查詢要傳送使用者名稱的位置
				if(strcmp(recvBuf, "all") == 0)//實現群發
				{
					memset(recvBuf, 0, sizeof(recvBuf));
					recv(sockConn1, recvBuf, sizeof(recvBuf), 0);
					for (int i = 0; i < nl; i++)
					{
						if (online[i] == 1&&i!=findu(sockConn1))
						{
							string a = user[n] + ": ";
							const char* pp = a.data();
							sockNum = finds(user[i]);
							if (send(sockConn[sockNum], pp, sizeof(pp), 0) < 0) //,sizeof(buf),0)<0)
								cout << "send failed";
							send(sockConn[sockNum], recvBuf, sizeof(recvBuf), 0);
						}
					}
				}
				else
				{
					if (strcmp(recvBuf, "退出") == 0)//使用者選擇退出
					{

						int i = findu(sockConn1);
						online[i] = 0;
						closesocket(sockConn1);
					}
					if (online[index]==1&&index != -1)
					{

						int sockNum = match[index];//找到此使用者名稱的套接
						
						int nRecv = ::recv(sockConn1, recvBuf, sizeof(recvBuf), 0);
						cout << endl;
						if (nRecv > 0)//實現轉發給其他客戶端 
						{
							string a=user[n] +": ";//實現能看到是誰發的
							cout << id1 << "號客戶說:" << recvBuf << endl;
							const char* ppp = a.data();
							send(sockConn[sockNum], ppp, sizeof(recvBuf), 0);
							send(sockConn[sockNum], recvBuf, sizeof(recvBuf), 0);
							//send(sockConn1, "傳送的使用者名稱存在", sizeof(recvBuf), 0);
							//if (send(sockConn[0], recvBuf, sizeof(recvBuf), 0) < 0)
								//cout << "傳送失敗";

							//send(sockConn[0], recvBuf, sizeof(recvBuf), 0);
						}
						else
							break;

					}
					if (online[index] == 0&&index!=-1)
					{
						memset(recvBuf, 0, sizeof(recvBuf));
						recv(sockConn1, recvBuf, sizeof(recvBuf), 0);
						send(sockConn1, "使用者不線上", sizeof(recvBuf), 0);
					}
					if(index==-1)//傳送的使用者名稱不存在
					{
						memset(recvBuf, 0, sizeof(recvBuf));
						recv(sockConn1, recvBuf, sizeof(recvBuf), 0);
						send(sockConn1, "傳送的使用者名稱不存在", sizeof(recvBuf), 0);
					}
					
				}
				
			}

		}
	}
	if (strcmp(recvBuf, "2") == 0) //客戶端選擇註冊
	{
		cout << "選擇註冊服務" << endl;
		memset(users, 0, sizeof(users));
		if (recv(sockConn1, users, sizeof(users), 0) < 0)//接收使用者名稱
			cout << "register failed" << endl;
		int index = find(user, users);//看看是否已存在使用者名稱
		send(sockConn1, "ack", sizeof(recvBuf), 0);
									  //cout << index <<users << endl;
		if (index != -1)//find
		{
			cout << "使用者名稱已存在" << endl;
			if (send(sockConn1, "使用者名稱已存在", sizeof(recvBuf), 0) < 0)
			{
				cout << "使用者註冊失敗" << endl;
			}
		}
		if (index == -1)//register
		{
			cout << "使用者名稱未註冊過" << endl;
			memset(pws, 0, sizeof(pws));
			if (recv(sockConn1, pws, sizeof(pws), 0) < 0)//接收密碼
				cout << "failed pws" << endl;
			else//接收密碼 新增使用者和密碼
			{
				cout << "已經接收到密碼" << pws << endl;
				int location = nul_index(user);//尋找可以插入的空位
				cout << "找到空位在1+" << location << endl;
				if (location == nl)//插入已滿
				{
					cout << "註冊已滿" << endl;
					if (send(sockConn1, "註冊已滿", sizeof(recvBuf), 0) < 0)//發給客戶已滿資訊
						cout << "send failed" << endl;
				}
				else//註冊
				{
					cout << "開始註冊:" << endl;
					user[location] = users;
					pw[location] = pws;
					cout << pw[location] << "aaa" << user[location] << endl;
					if (send(sockConn1, "註冊成功", sizeof(recvBuf), 0) < 0)//發給客戶已滿資訊
						cout << location + 1 << "位使用者" << "註冊成功" << endl;
				}

			}

		}
	}
	return recvBuf;
}
void* send1(void* args) {
	int id2 = (unsigned int)pthread_getw32threadid_np(pthread_self()) / 2;

	SOCKET sockClient1 = *((SOCKET*)args);//建立套接字
	char buff1[10000];


	while (true) {

		//cout<<"請輸入"<<endl;
		cin >> buff1;
		if (buff1 == "") {
			break;
		}
		int e = send(sockConn[0], buff1, sizeof(buff1), 0);
		if (e == SOCKET_ERROR) {
			printf("send failed");
			break;
		}
		/*e = send(sockConn[1], buff1, sizeof(buff1), 0);
		if (e == SOCKET_ERROR) {
			printf("send failed");
			break;
		}
		cout << "我說:" << buff1 << endl;*/
	}
	return buff1;
}
void* setClient(void* args)
{
	char buf[10000] = "Server: hello, I am a server.....";
	SOCKET sockClient = *((SOCKET*)args);//建立套接字
										 // printf("Accept client IP:[%s]\n", inet_ntoa(addrClient.sin_addr));
										 //傳送資料
										 //send1(sockConn);
	
	int iSend = send(sockClient, buf, sizeof(buf), 0);
	if (iSend == SOCKET_ERROR) {
		printf("send failed");

	}
	
	pthread_t tidss[2];
	int ret = pthread_create(&tidss[0], NULL, send1, (void*)&sockClient); //引數:建立的執行緒id,執行緒引數,執行緒執行函式的起始地址,執行函式的引數
	if (ret != 0) //建立執行緒成功返回0
	{
		cout << "pthread_create error:error_code=" << ret << endl;
	}
	recv1((void*)&sockClient);
	return buf;
}
int main()
{
	WSADATA wsaData;//WSADATA結構被用來儲存函式WSAStartup返回的Windows Sockets初始化資訊
	int port = 5099;

	char buf[] = "Server: hello, I am a server.....";

	if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) //載入套接字型檔
	{
		printf("Failed to load Winsock");
		return 0;
	}

	//建立用於監聽的套接字
	SOCKET sockSrv = socket(AF_INET, SOCK_STREAM, 0);//ipv4協議,流式傳輸 
	SOCKADDR_IN addrSrv;//此資料結構用做bind、connect、recvfrom、sendto等函式的引數,指明地址資訊。 
	addrSrv.sin_family = AF_INET;
	addrSrv.sin_port = htons(port); //1024以上的埠號
	addrSrv.sin_addr.S_un.S_addr = htonl(INADDR_ANY); //INADDR_ANY 代表任意ip
													  //繫結套接字 
	int retVal = bind(sockSrv, (LPSOCKADDR)&addrSrv, sizeof(SOCKADDR_IN));
	if (retVal == SOCKET_ERROR) {
		printf("Failed bind:%d\n", WSAGetLastError());
		return 0;
	}

	if (listen(sockSrv, 10) == SOCKET_ERROR) {//10代表允許連線的個數
		printf("Listen failed:%d", WSAGetLastError());
		return 0;
	}

	SOCKADDR_IN addrClient;
	int len = sizeof(SOCKADDR);

	int i = 0;
	while (1)
	{
		//等待客戶請求到來
		sockConn[i] = accept(sockSrv, (SOCKADDR *)&addrClient, &len);//會阻塞程序,直到有客戶端連線上來為止
		if (sockConn[i] == SOCKET_ERROR) {
			printf("Accept failed:%d", WSAGetLastError());
			break;
		}
		pthread_t tids[10];
		int res = pthread_create(&tids[i], NULL, setClient, (void*)&sockConn[i]);
		if (res != 0) //建立執行緒成功返回0
		{
			cout << "pthread_create error:error_code=" << res << endl;
		}
		i++;
	}

	closesocket(sockSrv);
	WSACleanup();
	system("pause");
	return 1;
}

客戶端核心程式碼:

介面1:


// connent1Dlg.cpp: 實現檔案
//

#include "stdafx.h"
#include "connent1.h"
#include "connent1Dlg.h"
#include "afxdialogex.h"
#include <WinSock2.h>
#include <stdio.h> 
#include <pthread.h>
#include <io.h>  
#include <fcntl.h>
#pragma comment(lib, "pthreadVC2.lib")
#pragma comment(lib, "ws2_32.lib")
#include<iostream>
#include "Cmessage.h"
using namespace std;
#ifdef _DEBUG
#define new DEBUG_NEW
#endif


char user[10];
char pw[20];
Cmessage  Dlg;
int num;
char buff[1000];
char nUser[1000];
//SOCKET sockClient;
bool success = false;
class CAboutDlg : public CDialogEx
{
public:
	CAboutDlg();

// 對話方塊資料
#ifdef AFX_DESIGN_TIME
	enum { IDD = IDD_ABOUTBOX };
#endif

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

// 實現
protected:
	DECLARE_MESSAGE_MAP()
};

CAboutDlg::CAboutDlg() : CDialogEx(IDD_ABOUTBOX)
{
}

void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialogEx::DoDataExchange(pDX);
}

BEGIN_MESSAGE_MAP(CAboutDlg, CDialogEx)
END_MESSAGE_MAP()


// Cconnent1Dlg 對話方塊



Cconnent1Dlg::Cconnent1Dlg(CWnd* pParent /*=nullptr*/)
	: CDialogEx(IDD_CONNENT1_DIALOG, pParent)
	, m_user(_T(""))
	, m_pw(_T(""))
	//, m_show(_T(""))
	//, m_message(_T(""))
	//, sUser(_T(""))
	//, suser(_T(""))
{
	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}

void Cconnent1Dlg::DoDataExchange(CDataExchange* pDX)
{
	CDialogEx::DoDataExchange(pDX);
	//DDX_Control(pDX, IDC_EDIT1, user);
	DDX_Text(pDX, IDC_EDIT2, m_pw);
	DDX_Text(pDX, IDC_EDIT1, m_user);
	//DDX_Text(pDX, IDC_EDIT3, m_show);
	//DDX_Text(pDX, IDC_EDIT4, m_message);
	//DDX_Control(pDX, IDC_EDIT3, edit3);
	//DDX_Text(pDX, IDC_EDIT5, sUser);//之前的類變數使用者名稱重複。不區分大小寫
	//DDX_Text(pDX, IDC_EDIT7, suser);
	//DDX_Control(pDX, IDC_COMBO1, m_chosecom);
}

BEGIN_MESSAGE_MAP(Cconnent1Dlg, CDialogEx)
	ON_WM_SYSCOMMAND()
	ON_WM_PAINT()
	ON_WM_QUERYDRAGICON()
	ON_EN_CHANGE(IDC_EDIT1, &Cconnent1Dlg::OnEnChangeEdit1)
	ON_BN_CLICKED(IDC_BUTTON1, &Cconnent1Dlg::OnBnClickedButton1)
	//ON_BN_CLICKED(IDC_BUTTON2, &Cconnent1Dlg::OnBnClickedButton2)
	ON_BN_CLICKED(IDC_BUTTON3, &Cconnent1Dlg::OnBnClickedButton3)
	//ON_CBN_SELCHANGE(IDC_COMBO1, &Cconnent1Dlg::OnCbnSelchangeCombo1)
END_MESSAGE_MAP()


// Cconnent1Dlg 訊息處理程式

BOOL Cconnent1Dlg::OnInitDialog()
{
	CDialogEx::OnInitDialog();

	// 將“關於...”選單項新增到系統選單中。

	// IDM_ABOUTBOX 必須在系統命令範圍內。
	ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
	ASSERT(IDM_ABOUTBOX < 0xF000);

	CMenu* pSysMenu = GetSystemMenu(FALSE);
	if (pSysMenu != nullptr)
	{
		BOOL bNameValid;
		CString strAboutMenu;
		bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX);
		ASSERT(bNameValid);
		if (!strAboutMenu.IsEmpty())
		{
			pSysMenu->AppendMenu(MF_SEPARATOR);
			pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
		}
	}

	// 設定此對話方塊的圖示。  當應用程式主視窗不是對話方塊時,框架將自動
	//  執行此操作
	SetIcon(m_hIcon, TRUE);			// 設定大圖示
	SetIcon(m_hIcon, FALSE);		// 設定小圖示

	// TODO: 在此新增額外的初始化程式碼
	//edit3 = (CEdit *)GetDlgItem(IDC_EDIT3);
	//GetDlgItem(IDC_EDIT4)->SetWindowText(_T("this is a test program!"));
	return TRUE;  // 除非將焦點設定到控制元件,否則返回 TRUE
}

void Cconnent1Dlg::OnSysCommand(UINT nID, LPARAM lParam)
{
	if ((nID & 0xFFF0) == IDM_ABOUTBOX)
	{
		CAboutDlg dlgAbout;
		dlgAbout.DoModal();
	}
	else
	{
		CDialogEx::OnSysCommand(nID, lParam);
	}
}

// 如果向對話方塊新增最小化按鈕,則需要下面的程式碼
//  來繪製該圖示。  對於使用文件/檢視模型的 MFC 應用程式,
//  這將由框架自動完成。

void Cconnent1Dlg::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
	{
		CDialogEx::OnPaint();
	}
}

//當用戶拖動最小化視窗時系統呼叫此函式取得游標
//顯示。
HCURSOR Cconnent1Dlg::OnQueryDragIcon()
{
	return static_cast<HCURSOR>(m_hIcon);
}



void Cconnent1Dlg::OnEnChangeEdit1()
{
	// TODO:  如果該控制元件是 RICHEDIT 控制元件,它將不
	// 傳送此通知,除非重寫 CDialogEx::OnInitDialog()
	// 函式並呼叫 CRichEditCtrl().SetEventMask(),
	// 同時將 ENM_CHANGE 標誌“或”運算到掩碼中。

	// TODO:  在此新增控制元件通知處理程式程式碼
}


void Cconnent1Dlg::OnBnClickedButton1()
{
	// TODO: 在此新增控制元件通知處理程式程式碼
	UpdateData(true);

	
	//載入套接字
	WSADATA wsaData;
	char buff[10000];
	memset(buff, 0, sizeof(buff));

	if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
	{
		printf("Failed to load Winsock");
		//return 0;
	}

	SOCKADDR_IN addrSrv; //服務端地址
	addrSrv.sin_family = AF_INET;
	addrSrv.sin_port = htons(5099);
	addrSrv.sin_addr.S_un.S_addr = inet_addr("127.0.0.1 ");

	//建立客戶端套接字
	 sockClient = socket(AF_INET, SOCK_STREAM, 0);//流步套接字
	if (SOCKET_ERROR == sockClient) {
		printf("Socket() error:%d", WSAGetLastError());
		//return 0;
	}

	//向伺服器發出連線請求
	if (connect(sockClient, (struct  sockaddr*)&addrSrv, sizeof(addrSrv)) == INVALID_SOCKET) {
		printf("Connect failed:%d", WSAGetLastError());
		//return 0;
	}
	else
	{   //先來一個把CString轉換成char*方法
		/*int i;
		for (i = 0; i < m_user.GetLength(); i++) 
		{
			user[i] = (char)(m_user.GetAt(i));
		}          
		user[i] = '\0';
		i = 0;
		for (i = 0; i < m_pw.GetLength(); i++)
		{
			pw[i] = (char)(m_pw.GetAt(i));
		}
		pw[i] = '\0';*/
		wchar_t *ptr1, *ptr2;
		ptr1 = m_user.GetBuffer(m_user.GetLength() * sizeof(wchar_t));
		WideCharToMultiByte(CP_ACP, 0, (LPCTSTR)ptr1, -1, user, sizeof(user), NULL, NULL);
		m_user.ReleaseBuffer();
		ptr2 = m_pw.GetBuffer(m_pw.GetLength() * sizeof(wchar_t));
		WideCharToMultiByte(CP_ACP, 0, (LPCTSTR)ptr2, -1, pw, sizeof(pw), NULL, NULL);
		m_pw.ReleaseBuffer();
		recv(sockClient, buff, sizeof(buff), 0);
		//printf("%s\n", buff);
		int number;
		    send(sockClient, "1", sizeof(user), 0);//傳送服務情況 
			//Sleep(1000);
			recv(sockClient, buff, sizeof(buff), 0);
			send(sockClient, user, sizeof(user), 0);//傳送使用者名稱 
				//cout << "send user failed";
			//Sleep(1000);
			recv(sockClient, buff, sizeof(buff), 0);
		    send(sockClient, pw, sizeof(pw), 0);
			//Sleep(1000);
				//cout << "send pw failed";
			//recv(sockClient, buff, sizeof(buff), 0);
			memset(buff, 0, sizeof(buff));
			recv(sockClient, buff, sizeof(buff), 0);
			if (strcmp(buff, "使用者名稱不存在") == 0)
			{
				//cout << "使用者名稱不存在";
				AfxMessageBox(_T("使用者名稱不存在!"));
				//return ;
			}
		    if (strcmp(buff, "密碼錯誤") == 0)
			{
				AfxMessageBox(_T("密碼錯誤!"));
				//return ;
			}
			if (strcmp(buff, "該使用者已存在") == 0)
			{
				AfxMessageBox(_T("該使用者已存在!"));
				//return ;
			}
			if (strcmp(buff, "密碼正確") == 0)
			{
				AfxMessageBox(_T("登入成功!"));
				GetDlgItem(IDC_BUTTON1)->EnableWindow(FALSE);
				success = true;
			}
			if (success)
			{   
				//AfxBeginThread(recv_thd, NULL);
				//this->ShowWindows(SW_HIDE);//當前介面隱藏
				  //需要新增該C***Dlg.h標頭檔案,否則編譯通不過
				Dlg.sockClient1 = sockClient;
				//Dlg.create();
				//Dlg->Create(IDD_DIAGLOG_MAIN, GetDesktopWindow());
				Dlg.DoModal();
				/*pthread_t tids[10];
				int res = pthread_create(&tids[0], NULL, recv1, (void*)&sockClient);
				if (res != 0) //建立執行緒成功返回0
				{
					cout << "pthread_create error:error_code=" << res << endl;
				}*/
				
				
				//recv1((void*)&sockClient);
				
			}
		//UpdateData(false);
	}
	
	//關閉套接字
	//closesocket(sockClient);
	//WSACleanup();

}
void Cconnent1Dlg::Update(CString s)
{
	edit3.ReplaceSel(s);
}
/*void Cconnent1Dlg::OnBnClickedButton2()
{
	// TODO: 在此新增控制元件通知處理程式程式碼
	UpdateData(true);
	//num = (char)(.GetAt(0));
	/*int i;
	for (i = 0; i < m_message.GetLength(); i++)
	{
		buff[i] = (char)(m_message.GetAt(i));
	}
	buff[i] = '\0';
	int i = 0;
	memset(nUser,0,sizeof(nUser));
	for (i=0; i < suser.GetLength(); i++)
	{
		nUser[i] = (char)(suser.GetAt(i));
	}
	nUser[i] = '\0';
	//下面是將CString轉為char*的方法
	 wchar_t *ptr; ptr = m_message.GetBuffer(m_message.GetLength() * sizeof(wchar_t)); 
	WideCharToMultiByte(CP_ACP, 0, (LPCTSTR)ptr, -1, buff, sizeof(buff), NULL, NULL);
	m_message.ReleaseBuffer();
	//char *buff1=(LPSTR)(LPCTSTR)m_message;
	//buff[0] = num;
	send(sockClient, nUser,sizeof(nUser), 0);
	Sleep(1);
	if (send(sockClient, buff, sizeof(buff), 0)<0)
		AfxMessageBox(_T("傳送失敗!"));
	
		//AfxMessageBox(_T("傳送成功!"));
		//}
	//memset(buff, 0, sizeof(buff));
	//recv(sockClient,buff,sizeof(buff),0);
	
}*/


void Cconnent1Dlg::OnBnClickedButton3()
{
	// TODO: 在此新增控制元件通知處理程式程式碼
	UpdateData(true);

	//載入套接字
	WSADATA wsaData;
	char buff[10000];
	memset(buff, 0, sizeof(buff));//

	if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
	{
		printf("Failed to load Winsock");
		//return 0;
	}

	SOCKADDR_IN addrSrv; //服務端地址
	addrSrv.sin_family = AF_INET;
	addrSrv.sin_port = htons(5099);
	addrSrv.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");

	//建立客戶端套接字
	sockClient = socket(AF_INET, SOCK_STREAM, 0);//流步套接字
	if (SOCKET_ERROR == sockClient) {
		printf("Socket() error:%d", WSAGetLastError());
		//return 0;
	}

	//向伺服器發出連線請求
	if (connect(sockClient, (struct  sockaddr*)&addrSrv, sizeof(addrSrv)) == INVALID_SOCKET) {
		printf("Connect failed:%d", WSAGetLastError());
		//return 0;
	}
	else
	{
		wchar_t *ptr1,*ptr2; 
		ptr1 = m_user.GetBuffer(m_user.GetLength() * sizeof(wchar_t));
		WideCharToMultiByte(CP_ACP, 0, (LPCTSTR)ptr1, -1, user, sizeof(user), NULL, NULL);
		m_user.ReleaseBuffer();
		ptr2 = m_pw.GetBuffer(m_pw.GetLength() * sizeof(wchar_t));
		WideCharToMultiByte(CP_ACP, 0, (LPCTSTR)ptr2, -1, pw, sizeof(pw), NULL, NULL);
		m_pw.ReleaseBuffer();
		recv(sockClient, buff, sizeof(buff), 0);
		//傳送給伺服器註冊資訊
		send(sockClient, "2", sizeof(user), 0);//傳送請求服務型別,為1表示登入,為2表示註冊
		recv(sockClient,buff,sizeof(buff),0);
		send(sockClient, user, sizeof(user), 0);//傳送使用者名稱 
		recv(sockClient,buff,sizeof(buff),0);
		send(sockClient, pw, sizeof(pw), 0);//傳送密碼
		//清空buff以接收伺服器傳來的訊息
		memset(buff, 0, sizeof(buff));
		recv(sockClient, buff, sizeof(buff), 0);
		if (strcmp(buff, "使用者名稱已存在") == 0)
		{
			AfxMessageBox(_T("使用者名稱已存在!"));
		}
		else
			if (strcmp(buff, "註冊已滿") == 0)
			{
				AfxMessageBox(_T("註冊使用者已滿!"));
			}
			else
				if (strcmp(buff, "註冊成功") == 0)
				{
					AfxMessageBox(_T("註冊成功!"));
					success = true;
				}
	}
}

介面2:

// Cmessage.cpp: 實現檔案
//

#include "stdafx.h"
#include "connent1.h"
#include "Cmessage.h"
#include "afxdialogex.h"
#include <WinSock2.h>
#include <stdio.h> 
#include <pthread.h>
#pragma comment(lib, "pthreadVC2.lib")
#pragma comment(lib, "ws2_32.lib")
#include<iostream>
#include "connent1Dlg.h"
using namespace std;
// Cmessage 對話方塊
char buff1[1000];
char nUser1[1000];
SOCKET sockClient2;
char num;
/*void* recv2(void* args)
{
	//SOCKET sockConn = *((SOCKET*)args);
	//HWND hWnd = *((HWND *)args);

	char recvBuf[10000];
	//Cmessage * dlg = (Cmessage *)AfxGetApp()->GetMainWnd()->GetSafeHwnd();
	
	//HWND hWnd = ::FindWindow(NULL, _T("Dialog"));      //得到對話方塊的控制代碼
	//Cmessage* pWnd = (Cmessage*)Cmessage::FromHandle(hWnd); //由控制代碼得到對話方塊的物件指標
	//接收資料
	if(hWnd==0)
		AfxMessageBox(_T("獲取當前控制代碼失敗"));
	while (hWnd!=0) {
		memset(recvBuf, 0, sizeof(recvBuf));
		int nRecv = ::recv(sockClient2, recvBuf, sizeof(recvBuf), 0);
		if (nRecv > 0)
		{
			if (strcmp(recvBuf, "傳送的使用者名稱不存在") == 0)//檢測使用者名稱是否存在

			{
				AfxMessageBox(_T("傳送的使用者名稱不存在!"));

			}
			else
			{
				CString a = CString(recvBuf) + _T("\n\r");
				//AfxMessageBox(_T("接收成功"));
				//Dlg->m_show = a;
				//pWnd->m_show1=a;
				pWnd->Update1(a);
				//m_show = a;
			}
		}
		else
			break;
	}
	return recvBuf;
}*/
UINT Cmessage::recv3(LPVOID p)
{
	//SOCKET sockConn = *((SOCKET*)args);
	//HWND hWnd = *((HWND *)p);

	char recvBuf[10000];
	Cmessage * dlg = (Cmessage *)p;

	//HWND hWnd = ::FindWindow(NULL, _T("Dialog"));      //得到對話方塊的控制代碼
	//Cmessage* pWnd = (Cmessage*)Cmessage::FromHandle(hWnd); //由控制代碼得到對話方塊的物件指標
															//接收資料
	//if (hWnd == 0)
	//	AfxMessageBox(_T("獲取當前控制代碼失敗"));
	while (true) {
		memset(recvBuf, 0, sizeof(recvBuf));
		int nRecv = ::recv(sockClient2, recvBuf, sizeof(recvBuf), 0);
		if (nRecv > 0)
		{
			if (strcmp(recvBuf, "傳送的使用者名稱不存在") == 0)//檢測使用者名稱是否存在

			{
				AfxMessageBox(_T("傳送的使用者名稱不存在!"));

			}
			else if (strcmp(recvBuf, "使用者不線上") == 0)//檢測使用者名稱是否存在

			{
				AfxMessageBox(_T("使用者不線上!"));

			}
			     else
			   {
				CString a = CString(recvBuf) + _T(" ");
				//AfxMessageBox(_T("接收成功"));
				//Dlg->m_show = a;
				//pWnd->m_show1=a;
				dlg->Update1(a);
				//m_show = a;
			    }
		}
		else
			break;
	}
	//return recvBuf;
	return true;
}

IMPLEMENT_DYNAMIC(Cmessage, CDialogEx)

Cmessage::Cmessage(CWnd* pParent /*=nullptr*/)
	: CDialogEx(IDD_DIALOG1_MAIN, pParent)
	, userNumber(_T(""))
	, m_message1(_T(""))
	, m_show1(_T(""))
{
	//Cconnent1Dlg *parent = (Cconnent1Dlg*)GetParent();
	//sockClient = parent->sockClient;
	//recv1(sockClient);
}

Cmessage::~Cmessage()
{
}

void Cmessage::DoDataExchange(CDataExchange* pDX)
{
	CDialogEx::DoDataExchange(pDX);
	DDX_Text(pDX, IDC_EDIT1, userNumber);
	DDX_Text(pDX, IDC_EDIT2, m_message1);
	DDX_Text(pDX, IDC_EDIT4, m_show1);
	DDX_Control(pDX, IDC_EDIT4, edit4);
}


BEGIN_MESSAGE_MAP(Cmessage, CDialogEx)
	ON_EN_CHANGE(IDC_EDIT2, &Cmessage::OnEnChangeEdit2)
	ON_BN_CLICKED(IDC_BUTTON1, &Cmessage::OnBnClickedButton1)
	ON_EN_CHANGE(IDC_EDIT4, &Cmessage::OnEnChangeEdit4)
	ON_BN_CLICKED(IDC_BUTTON3, &Cmessage::OnBnClickedButton3)
	ON_BN_CLICKED(IDC_BUTTON2, &Cmessage::OnBnClickedButton2)
END_MESSAGE_MAP()


// Cmessage 訊息處理程式


void Cmessage::OnEnChangeEdit2()
{
	// TODO:  如果該控制元件是 RICHEDIT 控制元件,它將不
	// 傳送此通知,除非重寫 CDialogEx::OnInitDialog()
	// 函式並呼叫 CRichEditCtrl().SetEventMask(),
	// 同時將 ENM_CHANGE 標誌“或”運算到掩碼中。

	// TODO:  在此新增控制元件通知處理程式程式碼

}
void Cmessage::Update1(CString s)
{
	edit4.ReplaceSel(s);
}

void Cmessage::OnBnClickedButton1()
{

	

	
	// TODO: 在此新增控制元件通知處理程式程式碼
	// TODO: 在此新增控制元件通知處理程式程式碼
	UpdateData(true);
	//num = (char)(.GetAt(0));
	//實現CString到char*的轉化
	wchar_t *ptr1; ptr1 = userNumber.GetBuffer(userNumber.GetLength() * sizeof(wchar_t));
	WideCharToMultiByte(CP_ACP, 0, (LPCTSTR)ptr1, -1, nUser1, sizeof(nUser1), NULL, NULL);
	userNumber.ReleaseBuffer();
	wchar_t *ptr2; ptr2 = m_message1.GetBuffer(m_message1.GetLength() * sizeof(wchar_t));
	WideCharToMultiByte(CP_ACP, 0, (LPCTSTR)ptr2, -1, buff1, sizeof(buff1), NULL, NULL);
	m_message1.ReleaseBuffer();
	//buff[0] = num;
	send(sockClient2, nUser1, sizeof(nUser1), 0);
	Sleep(1);
	if (send(sockClient2, buff1, sizeof(buff1), 0)<0)
		AfxMessageBox(_T("傳送失敗!"));

	//AfxMessageBox(_T("傳送成功!"));
	//}
	//memset(buff, 0, sizeof(buff));
	//recv(sockClient,buff,sizeof(buff),0);

}


void Cmessage::OnEnChangeEdit4()
{
	// TODO:  如果該控制元件是 RICHEDIT 控制元件,它將不
	// 傳送此通知,除非重寫 CDialogEx::OnInitDialog()
	// 函式並呼叫 CRichEditCtrl().SetEventMask(),
	// 同時將 ENM_CHANGE 標誌“或”運算到掩碼中。
	// TODO:  在此新增控制元件通知處理程式程式碼

}


void Cmessage::OnBnClickedButton3()
{
	Cconnent1Dlg *parent = (Cconnent1Dlg*)GetParent();
	sockClient2 = parent->sockClient;
	AfxBeginThread(recv3, this);
	GetDlgItem(IDC_BUTTON3)->EnableWindow(FALSE);
	/*pthread_t tids[10];
	int res = pthread_create(&tids[0], NULL, recv2, (void*)&this->m_hWnd);
	if (res != 0) //建立執行緒成功返回0
	{
		cout << "pthread_create error:error_code=" << res << endl;
	}
	*/
}


void Cmessage::OnBnClickedButton2()
{
	// TODO: 在此新增控制元件通知處理程式程式碼
	char a[100] = "退出";
	send(sockClient2, a, sizeof(a), 0);
	this->SendMessage(WM_CLOSE);
	AfxGetMainWnd()->SendMessage(WM_CLOSE);

}

主要效果:

(主要實現後面補充。。。)