易码技术论坛

 找回密码
 加入易码
搜索
查看: 178311|回复: 8

[原创]基于MFC的聊天程序设计

[复制链接]
发表于 2005-4-27 15:40:00 | 显示全部楼层
这里有个用win32ASM写的简单的聊天工具.
;************************************服务端代码**********************************
.386
.model flat,stdcall
option casemap:none
;*****************************************
include \masm32\include\windows.inc
include \masm32\include\kernel32.inc
include \masm32\include\user32.inc
include \masm32\include\ws2_32.inc
includelib \masm32\lib\user32.lib
includelib \masm32\lib\kernel32.lib
includelib \masm32\lib\ws2_32.lib
;*************************************
IDD_DIALOG_UDP EQU  101
IDC_EDIT_ADDR  EQU  1000
IDC_EDIT_SHOW  EQU  1001
IDC_EDIT_SEND  EQU  1002
WM_WINSOCK     EQU  WM_USER+1
UDP_PORT       EQU  1234H
;*************************************
.DATA
dCount     dd 0
MsgClient1  db "(Server)",0
MsgClient2  db "(Client)",0
.DATA?
hDlg       dd ?
hEditSend  dd ?
hIDOK      dd ?
hEditShow  dd ?
ipaddr     dd ?
wsd        WSADATA <>
sSockAddr  sockaddr_in <>
cSockAddr  sockaddr_in <>
IsConnect  dd ?
hSocket    dd ?
szBuffer   db 32768 dup(?)
szReadBuffer db 32768 dup(?)
;*************************************
.CONST
szErr         db "Error!",0
szFormat      db "%s%s:%s",0dh,0ah,0
szAddr        db "               ",0
ErrSendMsg    db "发送失败!     ",0
szErrConnect  db "尚未连接!     ",0
;*************************************
.code
_initUDP proc
local _stSin:sockaddr_in
local _szBuffer[1024]:byte
mov IsConnect,0
invoke EnableWindow,IDOK,FALSE
invoke RtlZeroMemory,addr cSockAddr,sizeof cSockAddr
invoke WSAStartup,02h,addr wsd
invoke socket,AF_INET,SOCK_DGRAM,NULL
.IF eax==INVALID_SOCKET
   invoke MessageBox,NULL,addr szErr,NULL,MB_OK
   ret
.ENDIF
mov hSocket,eax
invoke WSAAsyncSelect,hSocket,hDlg,WM_WINSOCK,FD_READ
invoke RtlZeroMemory,addr _stSin,sizeof _stSin
invoke htons,UDP_PORT
mov _stSin.sin_port,ax
mov _stSin.sin_family,AF_INET
mov _stSin.sin_addr,INADDR_ANY
invoke bind,hSocket,addr _stSin,sizeof _stSin
.IF eax==SOCKET_ERROR
   invoke MessageBox,NULL,addr szErr,addr szErr,MB_OK or MB_ICONWARNING
   invoke SendMessage,hDlg,WM_CLOSE,0,0
.ENDIF
invoke gethostname,addr _szBuffer,sizeof _szBuffer
invoke gethostbyname,addr _szBuffer
mov eax,[eax+12]
mov eax,[eax]
mov eax,[eax]
invoke inet_ntoa,eax
invoke SetDlgItemText,hDlg,IDC_EDIT_ADDR,eax
ret
_initUDP endp
_RecvData proc _hSocket
  local _dwStructLen
invoke RtlZeroMemory,addr szReadBuffer,sizeof szReadBuffer
invoke RtlZeroMemory,addr cSockAddr,sizeof cSockAddr
mov _dwStructLen,sizeof sockaddr_in
invoke recvfrom,_hSocket,addr szReadBuffer,sizeof szReadBuffer,0,addr cSockAddr,addr _dwStructLen
invoke WSAGetLastError
.IF eax!=SOCKET_ERROR
invoke RtlZeroMemory,addr szBuffer,sizeof szBuffer
lea esi,cSockAddr
assume esiTR sockaddr_in
mov eax,[esi].sin_addr
invoke inet_ntoa,eax
.IF eax
   mov ipaddr,eax
   invoke wsprintf,addr szBuffer,addr szFormat,ipaddr,addr MsgClient2,addr szReadBuffer
   invoke GetWindowTextLength,hEditShow
   invoke SendMessage,hEditShow,EM_SETSEL,eax,eax
   invoke SendMessage,hEditShow,EM_REPLACESEL,FALSE,addr szBuffer
   mov IsConnect,1
.ELSE
   invoke MessageBox,NULL,addr szErr,NULL,MB_OK
   mov IsConnect,0
.ENDIF
assume esi:nothing
.ENDIF
.IF IsConnect
   invoke EnableWindow,IDOK,TRUE
.ELSE
   invoke EnableWindow,IDOK,FALSE
.ENDIF
ret
_RecvData endp
;************************************************************
_SendData proc
local _szBuffer[1024]:byte
invoke RtlZeroMemory,addr szReadBuffer,sizeof szReadBuffer
invoke GetDlgItemText,hDlg,IDC_EDIT_SEND,addr szReadBuffer,sizeof szReadBuffer
invoke lstrlen,addr szReadBuffer
.IF eax
     mov ecx,eax
     invoke sendto,hSocket,addr szReadBuffer,ecx,0,addr cSockAddr,sizeof sockaddr_in
     .IF eax==-1
     mov IsConnect,0
     invoke EnableWindow,IDOK,FALSE
     invoke MessageBox,hDlg,addr ErrSendMsg,addr szErr,MB_OK or MB_ICONWARNING
     .ENDIF
.ENDIF
invoke SetDlgItemText,hDlg,IDC_EDIT_SEND,NULL
invoke RtlZeroMemory,addr szBuffer,sizeof szBuffer
invoke gethostname,addr _szBuffer,sizeof _szBuffer
invoke gethostbyname,addr _szBuffer
mov eax,[eax+12]
mov eax,[eax]
mov eax,[eax]
invoke inet_ntoa,eax
.IF eax
     invoke wsprintf,addr szBuffer,addr szFormat,eax,addr MsgClient1,addr szReadBuffer
     invoke GetWindowTextLength,hEditShow
     invoke SendMessage,hEditShow,EM_SETSEL,eax,eax
     invoke SendMessage,hEditShow,EM_REPLACESEL,FALSE,addr szBuffer
.ELSE
     invoke MessageBox,NULL,addr szErr,NULL,MB_OK
.endif
ret
_SendData endp
;*****************************************************************
_DlgProc proc hWnd,wMsg,wParam,lParam
    mov eax,wMsg
    .IF eax==WM_WINSOCK
      mov eax,lParam
         .IF ax==FD_READ
         invoke _RecvData,wParam
         .ELSE
         invoke MessageBox,NULL,addr szErr,NULL,MB_OK
         .ENDIF
    .ELSEIF eax==WM_INITDIALOG
       push hWnd
       pop hDlg
       invoke RegisterHotKey,hWnd,065h,MOD_CONTROL or MOD_ALT, 041h
       invoke GetDlgItem,hDlg,IDC_EDIT_SHOW
       mov hEditShow,eax
       invoke GetDlgItem,hDlg,IDC_EDIT_SEND
       mov hEditSend,eax
       invoke SetDlgItemText,hDlg,IDC_EDIT_ADDR,addr szAddr
       invoke _initUDP                 ;装入并初始化WINSOCK动态链接库
     .elseif eax== WM_HOTKEY
        invoke _SendData
        invoke SetFocus,hEditSend
    .ELSEIF eax==WM_CLOSE
        invoke UnregisterHotKey,hWnd,065h
        invoke closesocket,hSocket
        invoke WSACleanup
        invoke EndDialog,hDlg,NULL
     .ELSEIF eax==WM_COMMAND
        mov eax,wParam
       .if ax==IDOK
         .if IsConnect
           invoke _SendData
           invoke SetFocus,hEditSend
  .else
    invoke MessageBox,hDlg,addr szErrConnect,addr szErr,MB_OK or MB_ICONWARNING
  .endif
       .elseif ax==IDCANCEL
           invoke SendMessage,hDlg,WM_CLOSE,0,0
       .endif
     .ELSE
       mov eax,FALSE
       ret
     .ENDIF
     mov eax,TRUE
     ret
_DlgProc endp
;****************************************************************
;****************************************************************
start:
  invoke GetModuleHandle,NULL
  invoke DialogBoxParam,eax,IDD_DIALOG_UDP,NULL,addr _DlgProc,NULL
  invoke ExitProcess,NULL
end start
;**************************资源文件***************************
#include "e:\masm32\include\resource.h"
#define IDD_DIALOG_UDP          101
#define IDC_EDIT_ADDR           1000
#define IDC_EDIT_SHOW           1001
#define IDC_EDIT_SEND           1002
IDD_DIALOG_UDP DIALOG DISCARDABLE 0,0,210,146
STYLE DS_MODALFRAME|WS_POPUP|WS_CAPTION|WS_SYSMENU
CAPTION "UDP Server--Made By Sxy"
FONT 10,"System"
BEGIN
      DEFPUSHBUTTON "发送",IDOK,169,133,32,12
      PUSHBUTTON    "关闭",IDCANCEL,4,133,32,12
      EDITTEXT      IDC_EDIT_ADDR,70,10,135,12,ES_AUTOHSCROLL
      LTEXT         "本机IP地址",IDC_STATIC,6,12,62,9
      GROUPBOX      "网络操作",IDC_STATIC,2,2,207,24
      EDITTEXT      IDC_EDIT_SHOW,1,26,207,77,ES_MULTILINE|ES_AUTOVSCROLL|ES_AUTOHSCROLL|ES_READONLY
      EDITTEXT      IDC_EDIT_SEND,1,104,207,28,ES_MULTILINE|ES_AUTOVSCROLL|ES_AUTOHSCROLL
END
;***********************************************************************
发表于 2005-4-27 15:42:00 | 显示全部楼层
;***********************************客服端代码***************************************
.386
.model flat,stdcall
option casemap:none
;*****************************************
include \masm32\include\windows.inc
include \masm32\include\kernel32.inc
include \masm32\include\user32.inc
include \masm32\include\ws2_32.inc
includelib \masm32\lib\user32.lib
includelib \masm32\lib\kernel32.lib
includelib \masm32\lib\ws2_32.lib
;*************************************
IDD_DIALOG_UDP EQU  101
IDC_EDIT_ADDR  EQU  1000
IDC_EDIT_SHOW  EQU  1001
IDC_EDIT_SEND  EQU  1002
WM_WINSOCK     EQU  WM_USER+1
UDP_PORT       EQU  1234H
;*************************************
.DATA
dCount     dd 0
.DATA?
hDlg       dd ?
hEditSend  dd ?
hIDOK      dd ?
hEditShow  dd ?
ipaddr     dd ?
hSocket    dd ?
IsConnect  dd ?
wsd        WSADATA <>
sSockAddr  sockaddr_in <>
szBuffer   db 32768 dup(?)
szReadBuffer db 32768 dup(?)
;*************************************
.CONST
MsgClient1  db "Client",0
MsgClient2  db 'Server',0
szErr         db "Error!",0
szFormat      db "%s%s:%s",0dh,0ah,0
szAddr        db "               ",0
szErrSend     db "发送失败!      ",0
;*************************************
.code
_initUDP proc
local _szBuffer[1024]:byte
mov IsConnect,0
invoke EnableWindow,IDOK,FALSE
invoke WSAStartup,02h,addr wsd
invoke socket,AF_INET,SOCK_DGRAM,NULL
.IF eax==INVALID_SOCKET
   invoke MessageBox,NULL,addr szErr,NULL,MB_OK or MB_ICONWARNING
   ret
.ENDIF
mov hSocket,eax
invoke WSAAsyncSelect,hSocket,hDlg,WM_WINSOCK,FD_READ
ret
_initUDP endp
_RecvData proc _hSocket
  local _dwStructLen
  local _stSin:sockaddr_in
invoke RtlZeroMemory,addr szReadBuffer,sizeof szReadBuffer
invoke RtlZeroMemory,addr _stSin,sizeof sockaddr_in
mov _dwStructLen,sizeof sockaddr_in
invoke recvfrom,_hSocket,addr szReadBuffer,sizeof szReadBuffer,0,addr _stSin,addr _dwStructLen
invoke WSAGetLastError
.IF eax!=SOCKET_ERROR
invoke RtlZeroMemory,addr szBuffer,sizeof szBuffer
lea esi,_stSin
assume esiTR sockaddr_in
mov eax,[esi].sin_addr
invoke inet_ntoa,eax
.IF eax
   mov ipaddr,eax
   invoke SetDlgItemText,hDlg,IDC_EDIT_ADDR,ipaddr
   invoke wsprintf,addr szBuffer,addr szFormat,ipaddr,addr MsgClient2,addr szReadBuffer
   invoke GetWindowTextLength,hEditShow
   invoke SendMessage,hEditShow,EM_SETSEL,eax,eax
   invoke SendMessage,hEditShow,EM_REPLACESEL,FALSE,addr szBuffer
   mov IsConnect,1
.ELSE
   invoke MessageBox,NULL,addr szErr,NULL,MB_OK or MB_ICONWARNING
   mov IsConnect,0
.ENDIF
assume esi:nothing
.ENDIF
.IF IsConnect
invoke EnableWindow,IDOK,TRUE
.ELSE
invoke EnableWindow,IDOK,FALSE
.ENDIF
ret
_RecvData endp
;************************************************************
_SendData proc
local _szBuffer[1024]:byte
local _stSin:sockaddr_in
lea esi,_stSin
assume esiTR sockaddr_in
invoke RtlZeroMemory,addr _stSin,sizeof _stSin
invoke GetDlgItemText,hDlg,IDC_EDIT_ADDR,addr szBuffer,sizeof szBuffer
invoke inet_addr,addr szBuffer
.IF eax==INADDR_NONE
   invoke MessageBox,NULL,addr szErr,NULL,MB_OK or MB_ICONWARNING
   ret
.ENDIF
mov [esi].sin_addr,eax
mov [esi].sin_family,AF_INET
invoke htons,UDP_PORT
mov [esi].sin_port,ax
invoke RtlZeroMemory,addr szReadBuffer,sizeof szReadBuffer
invoke GetDlgItemText,hDlg,IDC_EDIT_SEND,addr szReadBuffer,sizeof szReadBuffer
invoke lstrlen,addr szReadBuffer
.IF eax
     mov ecx,eax
     invoke sendto,hSocket,addr szReadBuffer,ecx,0,addr _stSin,sizeof sockaddr_in
     .IF eax==-1
       invoke MessageBox,hDlg,addr szErrSend,addr szErr,MB_OK or MB_ICONWARNING
       mov IsConnect,0
     .ENDIF
.ENDIF
invoke SetDlgItemText,hDlg,IDC_EDIT_SEND,NULL
invoke RtlZeroMemory,addr szBuffer,sizeof szBuffer
invoke gethostname,addr _szBuffer,sizeof _szBuffer
invoke gethostbyname,addr _szBuffer
mov eax,[eax+12]
mov eax,[eax]
mov eax,[eax]
invoke inet_ntoa,eax
.IF eax
     invoke wsprintf,addr szBuffer,addr szFormat,eax,addr MsgClient1,addr szReadBuffer
     invoke GetWindowTextLength,hEditShow
     invoke SendMessage,hEditShow,EM_SETSEL,eax,eax
     invoke SendMessage,hEditShow,EM_REPLACESEL,FALSE,addr szBuffer
.ELSE
     invoke MessageBox,NULL,addr szErr,NULL,MB_OK
.endif
ret
_SendData endp
;*****************************************************************
_DlgProc proc hWnd,wMsg,wParam,lParam
    mov eax,wMsg
    .IF eax==WM_WINSOCK
      mov eax,lParam
         .IF ax==FD_READ
         invoke _RecvData,wParam
         .ELSE
         invoke MessageBox,NULL,addr szErr,NULL,MB_OK or MB_ICONWARNING
         .ENDIF
    .ELSEIF eax==WM_INITDIALOG
       push hWnd
       pop hDlg
       invoke RegisterHotKey,hWnd,065h,MOD_CONTROL or MOD_ALT, 041h
       invoke GetDlgItem,hDlg,IDC_EDIT_SHOW
       mov hEditShow,eax
       invoke GetDlgItem,hDlg,IDC_EDIT_SEND
       mov hEditSend,eax
       invoke SetDlgItemText,hDlg,IDC_EDIT_ADDR,addr szAddr
       invoke _initUDP                 ;装入并初始化WINSOCK动态链接库
     .elseif eax== WM_HOTKEY
        invoke _SendData
        invoke SetFocus,hEditSend
    .ELSEIF eax==WM_CLOSE
        invoke UnregisterHotKey,hWnd,065h
        invoke closesocket,hSocket
        invoke WSACleanup
        invoke EndDialog,hDlg,NULL
     .ELSEIF eax==WM_COMMAND
        mov eax,wParam
       .if ax==IDOK
           invoke _SendData
           invoke SetFocus,hEditSend
       .elseif ax==IDCANCEL
           invoke SendMessage,hDlg,WM_CLOSE,0,0
       .endif
     .ELSE
       mov eax,FALSE
       ret
     .ENDIF
     mov eax,TRUE
     ret
_DlgProc endp
;****************************************************************
;****************************************************************
start:
  invoke GetModuleHandle,NULL
  invoke DialogBoxParam,eax,IDD_DIALOG_UDP,NULL,addr _DlgProc,NULL
  invoke ExitProcess,NULL
end start
;**************************************资源文件*******************************************
#include "e:\masm32\include\resource.h"
#define IDD_DIALOG_UDP          101
#define IDC_EDIT_ADDR           1000
#define IDC_EDIT_SHOW           1001
#define IDC_EDIT_SEND           1002
IDD_DIALOG_UDP DIALOG DISCARDABLE 0,0,210,146
STYLE DS_MODALFRAME|WS_POPUP|WS_CAPTION|WS_SYSMENU
CAPTION "UDP Client--Made By Sxy"
FONT 10,"System"
BEGIN
      DEFPUSHBUTTON "发送",IDOK,169,133,32,12
      PUSHBUTTON    "关闭",IDCANCEL,4,133,32,12
      EDITTEXT      IDC_EDIT_ADDR,70,10,135,12,ES_AUTOHSCROLL
      LTEXT         "服务器IP地址",IDC_STATIC,6,12,62,9
      GROUPBOX      "网络操作",IDC_STATIC,2,2,207,24
      EDITTEXT      IDC_EDIT_SHOW,1,26,207,77,ES_MULTILINE|ES_AUTOVSCROLL|ES_AUTOHSCROLL|ES_READONLY
      EDITTEXT      IDC_EDIT_SEND,1,104,207,28,ES_MULTILINE|ES_AUTOVSCROLL|ES_AUTOHSCROLL
END
;*******************************************************************************
发表于 2005-4-27 15:44:00 | 显示全部楼层
晕。
还是c好。
发表于 2005-4-27 22:56:00 | 显示全部楼层
支持LEE,C好~~
 楼主| 发表于 2005-4-28 06:59:00 | 显示全部楼层
void CChatClientDlg::OnSend()
{

UpdateData(TRUE);

     int n;
     CString MSG;
     char message[1000];
     GetDlgItemText(IDC_EDITMSG,MSG);
     SetDlgItemText(IDC_EDITMSG,"");
     MSG=Name+":"+MSG;
     n=MSG.GetLength();
     sprintf(message,"%s",MSG.GetBuffer(n));
     message[n]=0;
     TheSocket.Send(message,n+1);

}

幸亏不是自己用API,用API真的很烦,但是很爽!


晕。

还是c好。



怎么这样说呀,用C++很方便啊?
发表于 2005-4-28 10:37:00 | 显示全部楼层
他的意思是与汇编相比  c好
发表于 2005-4-28 11:27:00 | 显示全部楼层
还是VC好!
发表于 2005-4-28 16:06:00 | 显示全部楼层
……这帖又水了……
什么东西好这种话题,可以打住了吧?等自己把一个东西用上几年后,再来评论也不迟。
 楼主| 发表于 2005-4-27 07:05:09 | 显示全部楼层 |阅读模式
MFC是MS  公司为方便广大程序员进行windows程序设计,在其提供的API函数的基础上建立的类库。MFC中的Csocket类库封装了许多进行网络通信的API函数,用Csocket进行网络程序设计是很方便的。现在就利用Csocket进行聊天程序设计进行设计:

服务器:

1、  拥有一个Socket监听端口,响应客户端的连接请求消息;

2、  拥有一个Socket表,在响应客户端的连接请求消息后向表中添加Socket,此Socket和发出该连接请求消息的客户端通信;

3、  每个Socket拥有一个Socket表指针,通过指针让所有的Socket共享一个Socket表(包含这个监听端口的Socket);

4、  任何Socket收到“数据接受请求消息”的时候将调用这个表的某些函数结合艘并处理数据(一般这个函数至少需要个参数Csocket*,在调用的时候将this传过去,在函数中先调用Rceive 接受数据,同时这个函数属于Csocket表,也能访问其他Socket,在分析数据后就能将数据发送到其他Socket了)。

客户端:

    拥有一个Socket来连接到服务器和接受数据,该Socket拥有一个对话框指针。在疮痂Socket是将指针志向当前对话框就能在收到“数据接受请求消息”访问对话框了。

这样一个聊天程序就很容易了:

1、  群聊:服务器响应多个客户(不小于2个)的连接。任何Socket在响应“数据接受请求消息”时调用Ccsocket的某个能将消息发向每个客户的函数。客户端负责发送聊天数据,接受数据时显示出来就行了;

2、  二人聊:服务器只响应2个客户的连接请求就行了。

(至于其他功能就更加容易了,我也不多说了。)

         谢谢,请指教!!!
您需要登录后才可以回帖 登录 | 加入易码

本版积分规则

Archiver|手机版|小黑屋|EMAX Studio

GMT+8, 2025-4-28 02:56 , Processed in 0.016831 second(s), 18 queries .

Powered by Discuz! X3.4

© 2001-2017 Comsenz Inc.

快速回复 返回顶部 返回列表