基于对话框的套接字编程

基于对话框的套接字编程

实验目的

  1. 理解Win32窗口应用程序的窗口机制、消息机制等工作原理。
  2. 掌握Win32窗口应用程序的程序框架和实现步骤。
  3. 掌握基于对话框的套接字编程方法和步骤。
    二、实验内容
    在VC++编程环境下,实现一个基于对话框的流式套接字C/S模式应用程序。要求建立Socket连接后,客户端可向服务器端发送信息并显示信息内容,服务器端可接收信息并显示信息的内容。
    程序运行界面如下图所示:
    在这里插入图片描述
    在这里插入图片描述

提示:服务器端对话框主要控件设置可参考下表,客户端可对照设置。
序号	控件类别	ID	标题(caption)	功能说明1	Dialog	IDD_TCPSRV	TCP服务器端	服务器端对话框2	Group box	默认	服务器端参数	参数组合框3	Static text	默认	IP	地址提示文本4	Static text	默认	端口	端口提示文本5	IP Address Control	IDC_SrvIP_IPC		IP地址输入框6	Edit Control	IDC_PORT_EDIT		端口地址输入框7	List box Control	IDC_RECVBUF_LISTBOX		接收信息列表框。注意:sort属性为否8	Button Control	IDC_CREATE_BUTTON	创建服务器	创建服务器按钮9	Button Control	IDC_RECV_BUTTON	接收数据	接收数据按钮10	Button Control	IDC_QUIT_BUTTON	退出	退出按钮

要求:本实验需要提供服务端程序和客户端程序源代码压缩包。
三、实验原理
Windows 程序设计是一种事件驱动方式的程序设计模式,主要是基于消息的。一个完整的Win32窗体程序的实现步骤大概可以分为6步:
1.设计窗口类(使用WNDCLASS类)
2.注册窗口(RegisterClass()函数)
3.创建窗口(CreateWindow()函数)
4.显示及更新窗口(ShowWindow()、updateWindow())
5.通过循环取消息(GetMessage())
6.实现窗口过程(WinProc函数)
对话框本质上也是一个窗体,其工作机制与窗体的工作机制相同。不过,在VS2012编程环境中设计对话框,可以充分利用图形化界面工具,在设计和实现上更为简单。一般简单的界面应用程序推荐使用对话框来实现。
四、实验步骤
1.编写程序,运行服务器端跟客户端
在这里插入图片描述

2.服务器端,创建IP及端口,客户端连接次服务器地址,成功连接
在这里插入图片描述

3.客户端发送数据,服务器点击接收数据
在这里插入图片描述

五、实验小结
通过实验,理解Win32窗口应用程序的窗口机制、消息机制等工作原理,掌握Win32窗口应用程序的程序框架和实现步骤,掌握基于对话框的套接字编程方法和步骤。
六、源码
服务器

#include "stdafx.h"
#include "TE03_Win32TcpServ.h"

//编程添加
#include "winsock2.h"
#pragma comment(lib,"ws2_32.lib")


#define MAX_LOADSTRING 100

// 全局变量:
HINSTANCE hInst;								// 当前实例
TCHAR szTitle[MAX_LOADSTRING];					// 标题栏文本
TCHAR szWindowClass[MAX_LOADSTRING];			// 主窗口类名

//编程添加
SOCKET sockServer,sockConnect;
SOCKADDR_IN  addrServer,addrClient;
char ip[16],port[5];
char sendBuf[256],recvBuf[256];
char clientBuf[999]="客户端: >",serverBuf[999]="服务器: >";
int addrLen=sizeof(SOCKADDR);

// 此代码模块中包含的函数的前向声明:
BOOL				InitInstance(HINSTANCE, int);
INT_PTR CALLBACK	TcpSrvProc(HWND, UINT, WPARAM, LPARAM);

int APIENTRY _tWinMain(_In_ HINSTANCE hInstance,
                     _In_opt_ HINSTANCE hPrevInstance,
                     _In_ LPTSTR    lpCmdLine,
                     _In_ int       nCmdShow)
{
	UNREFERENCED_PARAMETER(hPrevInstance);
	UNREFERENCED_PARAMETER(lpCmdLine);

 	// TODO: 在此放置代码。	
	MSG msg;
	HACCEL hAccelTable;
	
	// 执行应用程序初始化:
	if (!InitInstance (hInstance, nCmdShow))
	{
		return FALSE;
	}

	hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_TE03_WIN32TCPSERV));
	// 主消息循环:
	while (GetMessage(&msg, NULL, 0, 0))
	{
		if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
		{
			TranslateMessage(&msg);
			DispatchMessage(&msg);
		}
	}

	return (int) msg.wParam;	
}


BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
   HWND hWnd;

   hInst = hInstance; // 将实例句柄存储在全局变量中
  
   hWnd =CreateDialog(hInstance, MAKEINTRESOURCE(IDD_TCPSRV), GetDesktopWindow(), TcpSrvProc);

   if (!hWnd)
   {
      return FALSE;
   }

   ShowWindow(hWnd, nCmdShow);
   UpdateWindow(hWnd);

   return TRUE;
}


// “TCP服务器端”框的消息处理程序。
INT_PTR CALLBACK TcpSrvProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
	UNREFERENCED_PARAMETER(lParam);


	switch (message)
	{
	case WM_INITDIALOG:
		SetDlgItemText(hDlg,IDC_SrvIP_IPC,"127.0.0.1");	//设置ip文本框的内容
		SetDlgItemText(hDlg,IDC_PORT_EDIT,"5566");	//设置端口文本框的内容
		WSADATA wsaData;
		if(WSAStartup(MAKEWORD(2,2), &wsaData))	
		{
			MessageBox(hDlg,"Winsock加载失败","警告",0);
			WSACleanup();
		}
		return (INT_PTR)TRUE;

	case WM_COMMAND:
		switch(LOWORD(wParam) )
			{ 
			case IDC_QUIT_BUTTON: 	//单击了退出按钮
				EndDialog(hDlg, LOWORD(wParam));
				closesocket(sockServer);	//关闭套接字	
				WSACleanup();		//卸载WinSock协议栈
			return TRUE;
			
			case IDC_CREATE_BUTTON:		//单击了创建服务器按钮
				GetDlgItemText(hDlg,IDC_SrvIP_IPC,ip,16);	//获取编辑框中的IP值
				GetDlgItemText(hDlg,IDC_PORT_EDIT,port,5);
				EnableWindow(GetDlgItem(hDlg,IDC_CREATE_BUTTON),FALSE); //禁用按钮
				sockServer=socket(AF_INET,SOCK_STREAM,0);
				addrServer.sin_family=AF_INET;
				addrServer.sin_addr.S_un.S_addr=inet_addr(ip);
				addrServer.sin_port=htons(atoi(port));				
				bind(sockServer,(SOCKADDR*) &addrServer,addrLen); 	//绑定套接字
				listen(sockServer,5);			//监听
				sockConnect=accept(sockServer,(SOCKADDR*) &addrClient,&addrLen);//接受连接
				if(sockConnect!=INVALID_SOCKET)
					SendDlgItemMessage(hDlg,IDC_RECVBUF_LISTBOX,LB_ADDSTRING,0,(LPARAM)"客户端已经连接上");
				break;
							
			case IDC_RECV_BUTTON:			//单击了接收按钮
				recv(sockConnect,recvBuf,256,0);
				strcat(clientBuf,recvBuf);
				//将接收到的消息添加到列表框中
				SendDlgItemMessage(hDlg,IDC_RECVBUF_LISTBOX,LB_ADDSTRING,0,(LPARAM)clientBuf);
				strcpy(clientBuf, "客户端: >");				
				break;
		}//switch(LOWORD(wParam) )
		
	}//switch (message)
	return (INT_PTR)FALSE;
}

客户端

#include "stdafx.h"
#include "L09_TcpClient.h"
#include <winsock2.h>
#pragma comment(lib,"ws2_32.lib")

#define MAX_LOADSTRING 100

// 全局变量:
HINSTANCE hInst;								// 当前实例
TCHAR szTitle[MAX_LOADSTRING];					// 标题栏文本
TCHAR szWindowClass[MAX_LOADSTRING];			// 主窗口类名

SOCKET sockClient;			//声明客户端套接字
SOCKADDR_IN addrServer;

// 此代码模块中包含的函数的前向声明:
BOOL				InitInstance(HINSTANCE, int);
INT_PTR CALLBACK	TcpClientProc(HWND, UINT, WPARAM, LPARAM);

int APIENTRY _tWinMain(_In_ HINSTANCE hInstance,
                     _In_opt_ HINSTANCE hPrevInstance,
                     _In_ LPTSTR    lpCmdLine,
                     _In_ int       nCmdShow)
{
	UNREFERENCED_PARAMETER(hPrevInstance);
	UNREFERENCED_PARAMETER(lpCmdLine);

 	// TODO: 在此放置代码。
	MSG msg;
	HACCEL hAccelTable;

	// 初始化全局字符串
	LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
	LoadString(hInstance, IDC_L09_TCPCLIENT, szWindowClass, MAX_LOADSTRING);

	// 执行应用程序初始化:
	if (!InitInstance (hInstance, nCmdShow))
	{
		return FALSE;
	}

	hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_L09_TCPCLIENT));

	// 主消息循环:
	while (GetMessage(&msg, NULL, 0, 0))
	{
		if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
		{
			TranslateMessage(&msg);
			DispatchMessage(&msg);
		}
	}

	return (int) msg.wParam;
}


BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
   HWND hWnd;

   hInst = hInstance; // 将实例句柄存储在全局变量中

   hWnd = CreateDialog(hInstance, MAKEINTRESOURCE(IDD_TCPCLIENT), GetDesktopWindow(), TcpClientProc);

   if (!hWnd)
   {
      return FALSE;
   }

   ShowWindow(hWnd, nCmdShow);
   UpdateWindow(hWnd);

   return TRUE;
}


// “TCP客户端”框的消息处理程序。
INT_PTR CALLBACK TcpClientProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
	UNREFERENCED_PARAMETER(lParam);

	char ip[16], port[5];
	char sendbuf[256],recvbuf[256];	
	char serbuf[256]="服务器: >", clibuf[256]="客户端: >";
	int len =sizeof(SOCKADDR);

	switch (message)
	{
	case WM_INITDIALOG:
		SetDlgItemText(hDlg,IDC_IP_IPC,"127.0.0.1");
		SetDlgItemText(hDlg,IDC_PORT_EDIT,"5566");
		WSADATA wsaData;
		WSAStartup(MAKEWORD(2,2), &wsaData);		//加载协议栈
		sockClient=socket(AF_INET,SOCK_STREAM,0);		//创建套接字
		return (INT_PTR)TRUE;

	case WM_COMMAND:
		{
			switch(LOWORD(wParam))	{ 
				case IDC_QUIT_BUTTON:					//单击了退出按钮
					EndDialog(hDlg, LOWORD(wParam));
					closesocket(sockClient);
					WSACleanup();
					break;
		
				case IDC_CONN_BUTTON: 					//单击了“连接服务器”按钮
					GetDlgItemText(hDlg,IDC_IP_IPC,ip,16);		//获取ip
					GetDlgItemText(hDlg,IDC_PORT_EDIT,port,5);
					EnableWindow(GetDlgItem(hDlg,IDC_CONN_BUTTON),FALSE);	//禁用连接按钮
					addrServer.sin_family=AF_INET;
					addrServer.sin_addr.S_un.S_addr=inet_addr(ip);	
					addrServer.sin_port=htons(atoi(port));						
					if(connect(sockClient,(SOCKADDR*)&addrServer,sizeof(SOCKADDR)))
						MessageBox(NULL,"客户端连接服务器失败","警告",0);				
					else	
						MessageBox(NULL,"客户端连接服务器成功","通知",0);		
					break;
		
				case IDC_SEND_BUTTON: 		//单击了“发送”按钮
					GetDlgItemText(hDlg,IDC_SEND_EDIT,sendbuf,256);		//获得发送框的内容
					send(sockClient,sendbuf,strlen(sendbuf)+1,0);		//发送消息
					SetDlgItemText(hDlg,IDC_SEND_EDIT,"");		//清空发送框
					strcat(clibuf,sendbuf);				
					SendDlgItemMessage(hDlg,IDC_RECV_LISTBOX,LB_ADDSTRING,0,(LPARAM)clibuf);
					strcpy(clibuf, "客户端: >");  //重新给字符串赋值	
					break;
				
			}
		
		}//case WM_COMMAND:
	}
	return (INT_PTR)FALSE;
}
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

半夏风情

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值