Win32API 写的 Socket 聊天小程序

本文介绍了使用Windows编程技术创建一个简单的聊天程序,包括服务器端和客户端的代码实现,涉及窗口管理、网络通信和消息处理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

正在学 Windows编程,写了个聊天程序玩,鉴于学习中,借(co)鉴(py)了许多其他人的代码 害羞


效果如图:

服务器端客户端图

代码如下:

服务器端:

#pragma comment(lib, "Ws2_32.lib")
#include
#include
#include

#include
#include
#include

#define IDC_BTN_SEND 501
#define IDC_BTN_LAUNCH 502
#define IDC_TEXT_WRITE 5501
#define IDC_TEXT_SHOW 5502

#define MAX_LEN 1000

#define WM_SERVER_SOCKET 503

LRESULT CALLBACK WindowProc(
	_In_ HWND hwnd,
	_In_ UINT uMsg,
	_In_ WPARAM wParam,
	_In_ LPARAM lParam
);


HINSTANCE happ;

int WINAPI WinMain(
	_In_ HINSTANCE hInstance,
	_In_ HINSTANCE hPrevInstance,
	_In_ LPSTR lpCmdLine,
	_In_ int nShowCmd
	)
{
	WNDCLASS wc = {};
	wc.hbrBackground = (HBRUSH)(COLOR_WINDOWFRAME);
	wc.lpszClassName = _T("MWin");
	wc.lpfnWndProc = WindowProc;
	wc.hInstance = hInstance;

	RegisterClass(&wc);
	HWND hDesk = GetDesktopWindow();

	HWND hwnd = CreateWindow(
		_T("MWin"), 
		_T("Server"),
		WS_OVERLAPPEDWINDOW,
		35,
		36,
		460,
		580,
		NULL,
		NULL,
		hInstance,
		NULL);

	ShowWindow(hwnd, SW_SHOW);

	happ = hInstance;

	MSG msg;
	while(GetMessage(&msg, NULL, 0, 0))
	{
		TranslateMessage(&msg);
		DispatchMessage(&msg);
	}
	return 0;
}

LRESULT CALLBACK WindowProc(
	_In_ HWND hwnd,
	_In_ UINT uMsg,
	_In_ WPARAM wParam,
	_In_ LPARAM lParam
	)
{
	static PAINTSTRUCT ps;
	static HDC hdc;
	static int x = 50, y = 400;
	static int h = 40, w = 120;
	static HWND hDlg;
	static HWND hWrite, hShow, hBtn;

	static TCHAR *szpSendBuf, *szpRevcBuf, *tempBuf;

	static WORD wVersionRequested;
	static WSADATA wsaData;
	static int err;

	WORD lEvent, lError;
	static SOCKET sockConn, sockSrv;
	static SOCKADDR_IN addrSrv;
	static BOOL isAccepted = false;
	switch(uMsg)
	{
	case WM_CREATE:
		CreateWindow(_T("Button"), _T("Launch"),BS_PUSHBUTTON|WS_CHILD|WS_VISIBLE,
									360, 52 , 68, 28, hwnd, HMENU(IDC_BTN_LAUNCH), happ, NULL);
		CreateWindow(_T("Button"), _T("Send"), BS_PUSHBUTTON|WS_CHILD|WS_VISIBLE,
									285, 464 , 95, 40, hwnd, HMENU(IDC_BTN_SEND), happ, NULL);
		CreateWindow(_T("LISTBOX"), _T(""), 
									WS_CHILD|WS_VISIBLE|ES_LEFT|WS_BORDER| ES_READONLY|WS_VSCROLL,
									20, 20, 320, 404, hwnd, HMENU(IDC_TEXT_SHOW), happ, NULL);
		CreateWindow(_T("EDIT"), _T("ServerMachine"), WS_VISIBLE|WS_CHILD | WS_BORDER|ES_AUTOVSCROLL|ES_MULTILINE, 
									20, 444, 241, 69, hwnd, HMENU(IDC_TEXT_WRITE), happ, NULL);

		hWrite = GetDlgItem(hwnd, IDC_TEXT_WRITE);
		hShow = GetDlgItem(hwnd, IDC_TEXT_SHOW);

		break;
	case WM_COMMAND:
		if(LOWORD(wParam) == IDC_BTN_LAUNCH)
		{

			//开始通讯
			wVersionRequested = MAKEWORD(2,2);
			err = WSAStartup(wVersionRequested, &wsaData);
			if(err != 0)
			{
				return 0;
			}
			if(LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2)
			{
				WSACleanup();
				return 0;
			}
			sockSrv = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
			if( SOCKET_ERROR == WSAAsyncSelect( sockSrv, hwnd,
					WM_SERVER_SOCKET, FD_ACCEPT | FD_READ ) )
				{
					MessageBox(hwnd, TEXT("WSAAsyncSelect Error!"), TEXT("Server"),MB_OK );
					closesocket(sockSrv);
					WSACleanup();
				}

			addrSrv.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
			addrSrv.sin_family = AF_INET;
			addrSrv.sin_port = htons(6000);
			bind(sockSrv, (SOCKADDR*)&addrSrv, sizeof(SOCKADDR));
			listen(sockSrv, 5);

			SendMessage(hShow, LB_ADDSTRING, 0, (LPARAM)(_T("-------------Launch Success!-------------")));
		}
		else if(LOWORD(wParam) == IDC_BTN_SEND)
		{
			szpSendBuf = new TCHAR[100];
			SendMessage(hWrite, WM_GETTEXT, (WPARAM)(strlen(szpSendBuf)+1), (LPARAM)szpSendBuf);
			if(0 == GetWindowTextLength(hWrite))
			{
				MessageBox(hwnd, _T("No Empty Message!"), _T("Error"), 1);
			}
			else
			{
				INT sendFlag = send(sockConn, szpSendBuf, strlen(szpSendBuf)+1, 0);
				if(SOCKET_ERROR == sendFlag)
				{
					MessageBox(hwnd, _T("Sending Failed"), _T("ERROR"), MB_OK);
					break;
				}
				tempBuf = new TCHAR[100];
				wsprintf(tempBuf, "Server: %s", szpSendBuf);
				SendMessage(hShow, LB_ADDSTRING,0, (LPARAM)tempBuf);
				delete [] tempBuf;
			}
			delete [] szpSendBuf;
		}

		break;
	case WM_SERVER_SOCKET:
		lEvent = WSAGETSELECTEVENT(lParam);
		lError = WSAGETSELECTERROR(lParam);
		switch(lEvent)
		{
		case FD_ACCEPT:
			{
				if(lError)
				{
					MessageBox(hwnd, _T("Accept Error!"), _T("Server"), 0);
				}
				else
				{
					isAccepted = true;
				}
				sockConn = accept(sockSrv, NULL, NULL);
			}
			break;
		case FD_READ:
			{
				if(lError)
				{
					MessageBox(hwnd, _T("Read Error!"), _T("Server"), 0);
				}
				szpRevcBuf = new TCHAR[MAX_LEN];
				tempBuf = new TCHAR[MAX_LEN];
				recv(sockConn, szpRevcBuf, strlen(szpRevcBuf)+1, 0);
				wsprintf(tempBuf, "From Client: %s", szpRevcBuf);
				SendMessage(hShow, LB_ADDSTRING, 0, (LPARAM)tempBuf);
				delete [] szpRevcBuf;
				delete [] tempBuf;
			}
			break;
		case FD_CLOSE:
			{
				closesocket(sockSrv);
				closesocket(sockConn);
				isAccepted = false;
				InvalidateRect(hwnd, NULL, 1);
			}
			break;
		}
		break;
	case WM_PAINT:
		BeginPaint(hwnd, &ps);

		EndPaint(hwnd, &ps);
		break;
	case WM_QUIT:
		DestroyWindow(hwnd);
		break;
	case WM_KEYDOWN:
		break;
	case WM_DESTROY:
		PostQuitMessage(0);
		break;
	}
	return DefWindowProc(hwnd, uMsg, wParam, lParam);
}

客户端:
#pragma comment(lib, "Ws2_32.lib")
#include
#include
#include

#include
#include
#include

#define IDC_BTN_CONNECT 504
#define IDC_BTN_SEND 501
#define IDC_TEXT_WRITE 5501
#define IDC_TEXT_SHOW 5502

#define MAX_LEN 1000
#define WM_CLIENT_SOCKET 502

LRESULT CALLBACK WindowProc(
	_In_ HWND hwnd,
	_In_ UINT uMsg,
	_In_ WPARAM wParam,
	_In_ LPARAM lParam
);


HINSTANCE happ;

int WINAPI WinMain(
	_In_ HINSTANCE hInstance,
	_In_ HINSTANCE hPrevInstance,
	_In_ LPSTR lpCmdLine,
	_In_ int nShowCmd
	)
{
	WNDCLASS wc = {};
	wc.hbrBackground = (HBRUSH)(COLOR_WINDOWFRAME);
	wc.lpszClassName = _T("MWin");
	wc.lpfnWndProc = WindowProc;
	wc.hInstance = hInstance;

	RegisterClass(&wc);
	HWND hDesk = GetDesktopWindow();

	HWND hwnd = CreateWindow(
		_T("MWin"), 
		_T("Client"),
		WS_OVERLAPPEDWINDOW,
		35,
		36,
		460,
		580,
		NULL,
		NULL,
		hInstance,
		NULL);

	ShowWindow(hwnd, SW_SHOW);

	happ = hInstance;

	MSG msg;
	while(GetMessage(&msg, NULL, 0, 0))
	{
		TranslateMessage(&msg);
		DispatchMessage(&msg);
	}
	return 0;
}

LRESULT CALLBACK WindowProc(
	_In_ HWND hwnd,
	_In_ UINT uMsg,
	_In_ WPARAM wParam,
	_In_ LPARAM lParam
	)
{
	static PAINTSTRUCT ps;
	static int x = 50, y = 400;
	static int h = 40, w = 120;
	static HWND hDlg;
	static HWND hWrite, hShow, hBtn;

	WORD wVersionRequested ;
	WSADATA wsaData;
	static SOCKET sockClient,sockConn;
	SOCKADDR_IN addrSrv;
	TCHAR * szpRevcBuf,* szpSendBuf,*tempBuf ;
	static bool isConnected = false;
	int err;

	WORD lEvent,  lError;
	switch(uMsg)
	{
	case WM_CREATE:
		CreateWindow(_T("Button"), _T("Connect"), BS_PUSHBUTTON|WS_CHILD|WS_VISIBLE,
									360, 44 , 68, 41, hwnd, HMENU(IDC_BTN_CONNECT), happ, NULL);
		CreateWindow(_T("Button"), _T("Send"), BS_PUSHBUTTON|WS_CHILD|WS_VISIBLE,
									295, 464, 95, 40, hwnd, HMENU(IDC_BTN_SEND), happ, NULL);
		CreateWindow(_T("LISTBOX"), _T(""), 
									WS_CHILD|WS_VISIBLE|ES_LEFT|WS_BORDER| ES_READONLY|WS_VSCROLL,
									20, 20, 320, 404, hwnd, HMENU(IDC_TEXT_SHOW), happ, NULL);
		CreateWindow(_T("EDIT"), _T("ClientMachine"), WS_VISIBLE|WS_CHILD | WS_BORDER|ES_AUTOVSCROLL|ES_MULTILINE, 
									20, 444, 241, 69, hwnd, HMENU(IDC_TEXT_WRITE), happ, NULL);

		hWrite = GetDlgItem(hwnd, IDC_TEXT_WRITE);
		hShow = GetDlgItem(hwnd, IDC_TEXT_SHOW);

		break;
	case WM_COMMAND:
		if(LOWORD(wParam) == IDC_BTN_CONNECT)
		{

			wVersionRequested = MAKEWORD(2,2);
			err = WSAStartup(wVersionRequested, &wsaData);
			if(err != 0)
			{
				return 0;
			}
			if(LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2)
			{
				WSACleanup();
				return 0;
			}
			sockClient=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
				if( SOCKET_ERROR == WSAAsyncSelect( sockClient, hwnd,
					WM_CLIENT_SOCKET, FD_CONNECT | FD_READ ) )
				{
					MessageBox(hwnd, TEXT("WSAAsyncSelect Error!"), TEXT("Server"),MB_OK );
					closesocket(sockClient);
					WSACleanup();
				}

			addrSrv.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
			addrSrv.sin_family = AF_INET;
			addrSrv.sin_port = htons(6000);
			//bind(sockClient, (SOCKADDR*)&addrSrv, sizeof(SOCKADDR));
			
			INT returnErr = connect(sockClient, (SOCKADDR*)&addrSrv, sizeof(SOCKADDR));
			//if(SOCKET_ERROR != returnErr)
			//{
			//	SendMessage(hShow, LB_ADDSTRING, 0, (LPARAM)(_T("-------------Connect Success!--------------")));
			//}

		}
		else if(LOWORD(wParam) == IDC_BTN_SEND)
		{
			szpSendBuf = new TCHAR[100];
				SendMessage(hWrite, WM_GETTEXT,  (WPARAM)(strlen(szpSendBuf) + 1),(LPARAM)szpSendBuf);
				if (0 == GetWindowTextLength(hWrite))
				{
					MessageBox(hwnd, TEXT("不能发空消息"), TEXT("Error"), MB_OK);
				}	
				else
				{
					// 给客户端发送信息
					send(sockClient, szpSendBuf, strlen(szpSendBuf) +1, 0);
					tempBuf = new TCHAR[130];
					wsprintf(tempBuf,"Client : %s",szpSendBuf);
				    SendMessage(hShow, LB_ADDSTRING, 0, (LPARAM)tempBuf);
					delete []tempBuf;
				}
				delete []szpSendBuf;

		}
		break;

	case WM_CLIENT_SOCKET://自定义的网络消息
		{
		lEvent = WSAGETSELECTEVENT(lParam);
		lError = WSAGETSELECTERROR(lParam);
		
		switch(lEvent)
		{
		case FD_CONNECT:
			{
				if( lError )
				{
					MessageBox(hwnd, TEXT("Connect Timeout!"), TEXT("Client"), MB_OK );
				}
				else
				{
					SendMessage(hShow, LB_ADDSTRING, 0, (LPARAM)(_T("-------------Connect Success!--------------")));
					isConnected = true;
					InvalidateRect(hwnd,NULL,1);

				}
			}
			break;
			
		case FD_READ:
			{
				if( lError )
				{
					MessageBox(hwnd, TEXT("Receive Error!"), TEXT("Client"), MB_OK);
				}
				
				szpRevcBuf = new TCHAR[100];
				tempBuf    = new TCHAR[130];
				recv(sockClient, szpRevcBuf, strlen(szpRevcBuf) + 1, 0);
				wsprintf(tempBuf,"From Server : %s",szpRevcBuf);
				SendMessage(hShow, LB_ADDSTRING, 0, (LPARAM)tempBuf);
				delete []szpRevcBuf;
				delete []tempBuf;
				
			}
			break;
			
		case FD_CLOSE:
			{
				closesocket(sockClient);
				isConnected =  false;
				InvalidateRect(hwnd,NULL,1);
			}
			break;
		}//switch 2
		
		}
		break;

	case WM_PAINT:
		BeginPaint(hwnd, &ps);

		EndPaint(hwnd, &ps);
		break;
	case WM_QUIT:
		DestroyWindow(hwnd);
		break;
	case WM_KEYDOWN:
		break;
	case WM_DESTROY:
		PostQuitMessage(0);
		break;
	}
	return DefWindowProc(hwnd, uMsg, wParam, lParam);
}


评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值