Win32API 写的 Socket 聊天小程序

正在学 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
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
1.2 功能要求 (1)登录功能。 (2)客户可以通过服务器转发,实现一对一和多对多聊天。 (3)实现呼叫功能。 (4)客户端程序应该可以实时显示目前其它用户的状态。 (5)应该具有易用、美观的图形界面。 一、 实验目的: 1. 了解socket类的网络编程技术; 2. 熟悉socket聊天系统的结构和工作原理; 3. 掌握TCP传递消息的机制; 4. 应用delphi对该聊天系统进行程序的编。 二、 实验描述: 通过delphi编程实现局域网内的一个聊天系统,支持客户与服务器、客户与客户之间的消息传递,服务器允许多个客户端的聊天的功能,聊天记录的保存和查看的功能等。 三、 实验硬件、软件平台: 1. 硬件平台:多台PC机的一个局域网、Windows XP/2000、AMD Athlon64 X2 4000+ 、内存256MB以上、硬盘80G以上。 2. 软件平台:delphi7 1.3 运行环境 本系统基于WIN NT 和ACCESS XP设计,适用于WIN2000/WIN XP等系统,并需要安装office2000/office xp. 1.4 功能实现 1.登录验证功能。 2. 客户通过服务器转发,实现聊天功能。 3. 实时显示目前其它用户的状态。 4. 保存并能察看聊天纪录。 5.申请新的用户号码。 6. 易用、美观的图形界面,实现系统托盘。 二.技术路线 2.1 总体方案 为实现网络聊天的功能,采用Windows Socket编程,服务器与客户端采用了TCP/IP连接方式,在设计聊天方案时,实行将所有信息发往服务器端,再由服务器进行分别处理的思路,服务器端是所有信息的中心。 由于服务器端要保存用户信息,我们利用数据库来实现这一功能,因此首先需要建立用户信息数据库。 在客户端保存聊天纪录和用户号码这一功能的实现中,采用了文件系统设计。 在信息到来及好友上线时,通过闪动托盘图标和播放不同的音乐进行提示。 建立消息链表来保存用户接收的各种消息。 服务器及客户端的功能可划分为以下模块: 客户端: 1) 登陆功能:建立与服务器的连接并登陆,能显示登陆错误信息。 2) 界面显示:将在线好友显示在好友列表中,并实现系统托盘,加入工具栏便于操作。 3) 聊天功能:与好友聊天。 4) 聊天纪录:能保存聊天纪录,并能察看聊天纪录。 5) 信息提示:闪动托盘图标提示到来信息,并播放不同音乐来提示。 6) 其他: 用户登陆成功,将保存其号码,以便下次登陆时,不必再输入而可以直接选择,显示登陆时间。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值