目录
1、之前自己写了博客,让MFC和flash进行通信(MFC内部打开Flash然后通信的),现在想知道如何MFC和Flash之间通过网络Socket进行通信
1、运行效果:此时MFC和Flash1链接上,并且可以相互发送消息
①flash:ctrl+enter:发布:可以看到 :接下来完善MFC部分
①运行效果:此时MFC和Flash1链接上,并且可以相互发送消息
一、目的
1、之前自己写了博客,让MFC和flash进行通信(MFC内部打开Flash然后通信的),现在想知道如何MFC和Flash之间通过网络Socket进行通信
二、参考:
1、
三、问题+注意
1、
四、操作
1、运行效果:此时MFC和Flash1链接上,并且可以相互发送消息
1、flash
①创建flash
①导入Socket.as文件:HSocket.as
package
{
import flash.net.Socket;
import flash.utils.Timer;
import flash.events.TimerEvent;
import flash.events.Event;
import flash.events.IOErrorEvent;
import flash.events.ProgressEvent;
import flash.utils.ByteArray;
import flash.utils.Endian;
import flash.events.EventDispatcher;
import flash.display.Sprite;
import flash.net.XMLSocket;
import flash.system.Security;
import flash.system.SecurityDomain;
import flash.events.SecurityErrorEvent;
public class HSocket extends Sprite
{
public var sock:Socket;
private var serverIP:String = "127.0.0.1";
private var nPort:uint = 6000;
private var timer:Timer = new Timer(1000);
private var buffer:Array;
public var index:int;
public var m_receiveArray:ByteArray = new ByteArray();
public var recvStr:String = "";
public var netWorkConnect:Boolean=false;
public function HSocket(ip:String,port:uint)
{
//Security.allowDomain("*");
//Security.loadPolicyFile("xmlsocket://127.0.0.1:6000");
serverIP = ip;
port = nPort;
sock = new Socket();
}
public function Start()
{
//sock = new Socket(serverIP,nPort);
sock.addEventListener(Event.CONNECT,onSocketConnect);
sock.addEventListener(Event.CLOSE,onSocketClose);
sock.addEventListener(IOErrorEvent.IO_ERROR,onIOError);
sock.addEventListener(ProgressEvent.SOCKET_DATA,onRecvData);
sock.addEventListener(SecurityErrorEvent.SECURITY_ERROR,onSError);
timer.addEventListener(TimerEvent.TIMER,onTimer);
timer.start();
}
private function onSocketConnect(evt:Event)
{
sock.endian = Endian.LITTLE_ENDIAN;
trace("当前网络已经连接上!");
index = 1;
netWorkConnect=true;
}
private function onSocketClose(evt:Event)
{
//trace("网络断开连接");
index = 0;
}
private function onIOError(evt:IOErrorEvent)
{
trace("网络发生错误,断开!");
}
private function onSError(e:SecurityDomain):void
{
trace("安全沙箱不能启动服务器\n");
index = 5;
}
public function onRecvData(evt:ProgressEvent)
{
// trace("receive");
// buffer = null;
// buffer=new Array();
// while(sock.bytesAvailable)
// {
// buffer.push(sock.readInt());
// }
// trace(sock.readInt());
sock.readBytes(buffer,0,sock.bytesAvailable);
//m_receiveArray.length = 0;
m_receiveArray = null;
if(m_receiveArray == null)
{
m_receiveArray = new ByteArray();
}
//m_receiveArray.clear();
sock.readBytes(m_receiveArray,0,sock.bytesAvailable);
//trace("接收:" + m_receiveArray.toString());
recvStr = m_receiveArray.toString();
dispatchEvent(new Event("RecvData"));
}
public function GetRecvData():Array
{
return buffer;
}
public function SendData(id:int,p1:int,p2:int,p3:int,p4:int,p5:int)
{
if (sock == null || ! sock.connected)
{
return;
}
sock.writeInt(id);
sock.writeInt(p1);
sock.writeInt(p2);
sock.writeInt(p3);
sock.writeInt(p4);
sock.writeInt(p5);
sock.flush();
}
public function onTimer(evt:TimerEvent)
{
if (!sock.connected)
{
sock.connect(serverIP,nPort);
//trace("网络连接中,请稍后……");
netWorkConnect=false;
}
}
}
}
①flash关键帧编写:
import HSocket;
import flash.events.KeyboardEvent;
import flash.events.Event;
var socket:HSocket;
var serverIP:String = "127.0.0.1";
var nPort:uint = 6000;
var answerStr:String = "";//接收的演示灯答案
Start();
//初始化程序
function Start()
{
appInit();
if (! stage.hasEventListener(KeyboardEvent.KEY_UP))
{
stage.addEventListener(KeyboardEvent.KEY_UP,key_up);
}
}
function Destroy()
{
}
//网络Socket初始化
function appInit():void
{
socket = new HSocket(serverIP,nPort);
socket.Start();
socket.addEventListener("RecvData",onRecvData);
}
function onRecvData(e:Event):void
{
trace(socket.recvStr);
//答案字符串
if (0 == socket.recvStr.search("Answer:"))
{
answerStr = socket.recvStr.substr(7,socket.recvStr.length - 1);//substr() 方法可在字符串中抽取从 start 下标开始的指定数目的字符
}
switch (socket.recvStr)
{
case "choose" :
trace("11");
break;
}
}
function key_up(e:KeyboardEvent)
{
switch (e.keyCode)
{
case 0+96 :
socket.SendData(3,0,0,0,0,0);//发送让vc演示
trace("给mfc发了消息:3");
break;
}
}
①flash:ctrl+enter:发布:可以看到 :接下来完善MFC部分
1、MFC
①创建MFC
①igfSocket.h
#pragma once
#include <winsock2.h>
#pragma comment(lib, "ws2_32.lib")
// 一些需要用到的结构体和消息格式
#include <vector>
using namespace std;
struct Client
{
SOCKET sock;
string ip;
int type;
int gameState; //0失败 1成功
};
// 长消息格式
struct LONG_IGF_MSG
{
int id; // id,可以用作不同的客户端socket索引
int p1; // 控制参数1
int p2; // 控制参数2
int p3; // 控制参数3
int p4; // 控制参数4
int p5; // 参数5
char data[1000];// 数据
};
// 短消息格式
struct SHORT_IGF_MSG
{
int id;//控制源的ID
int p1;//参数1
int p2;//参数2
int p3;//参数3
int p4;//参数4
int p5;//参数5
};
// 回调函数原型(在程序中实现函数功能)
// 服务器检测到客户端连接触发
// 客户端检测到连接服务器成功触发
typedef void (CALLBACK *LPCONNECT)( SOCKET sock );
// 服务器检测到客户端连接断开触发
// 客户端检测到服务器关闭触发
typedef void (CALLBACK *LPDISCONNECT)( SOCKET sock );
// 先接收后发送过程
// cRecv传入时为接收到的数据|回调中为cSend填充要发送的数据
// 返回实际发送的字节数
// 如接收数据后不需要再发送响应数据回调中设返回值为0且不为cSend拷贝数据
typedef UINT (CALLBACK *LPPROC)( SOCKET sock, char* cRecv, char* cSend );
// 加载|卸载套接字模块
bool WINAPI igfInitSocket();
void WINAPI igfUnInitSocket();
bool WINAPI igfSocket2IP( SOCKET sock, char* out );
class igfSocket
{
public:
igfSocket( const char* ipaddr, UINT portid, UINT sendbuffersize, UINT recvbuffersize,
LPPROC pProc, LPCONNECT pConnect = NULL, LPDISCONNECT pDisconnect = NULL );
~igfSocket();
LPCONNECT connectfunc;
LPDISCONNECT disconnectfunc;
LPPROC procfunc;
char ip[16]; // 服务器地址
UINT port; // 端口号
UINT sendsize; // 一次发送最大字节数
UINT recvsize; // 一次接收的字节数|收满则触发回调
bool isThreadRun;
fd_set fdSocket; // 套接字集合
SOCKET sServer;
bool HasServer() { return m_isServer; }
SOCKET IP2Socket( const char* ipaddr );
SOCKET GetServerSocket(){return sServer;};
bool Send( SOCKET sock, const char* cSend, UINT len );
private:
HANDLE m_hThread;
bool m_isServer;
};
①igfSocket.cpp
#include "stdafx.h"
#include "igfSocket.h"
//-----------------------------------------------------------------------------
// 全局函数
//-----------------------------------------------------------------------------
bool WINAPI igfInitSocket()
{
WSADATA wsaData;
WORD wVersionRequested = MAKEWORD( 1, 1 );
int err = WSAStartup( wVersionRequested, &wsaData );
if( err != 0 )
return false;
if( LOBYTE( wsaData.wVersion ) != 1 ||
HIBYTE( wsaData.wVersion ) != 1 )
{
WSACleanup();
return false;
}
return true;
}
void WINAPI igfUnInitSocket()
{
WSACleanup();
}
bool WINAPI igfSocket2IP( SOCKET sock, char* out )
{
SOCKADDR_IN addr = {0};
int len = sizeof( addr );
if( getpeername( sock, (SOCKADDR*)&addr, &len ) != 0 )
return false;
strcpy_s( out, 16, inet_ntoa( addr.sin_addr ) );
return true;
}
//-----------------------------------------------------------------------------
// 线程函数
//-----------------------------------------------------------------------------
DWORD WINAPI ThreadServerFunc( LPVOID lParam )
{
igfSocket* ss = (igfSocket*)lParam;
int len = sizeof(SOCKADDR);
SOCKET sockServer = socket( AF_INET, SOCK_STREAM, 0 );
SOCKADDR_IN addrServer;
addrServer.sin_addr.S_un.S_addr = htonl( INADDR_ANY );
addrServer.sin_family = AF_INET;
addrServer.sin_port = htons( ss->port );
if( SOCKET_ERROR == bind( sockServer, (SOCKADDR*)&(addrServer), len ) )
return -1;
if( SOCKET_ERROR == listen( sockServer, FD_SETSIZE - 1 ) )
return -1;
ss->sServer = sockServer;
timeval tm;
tm.tv_sec = 1;
tm.tv_usec = 0;
FD_ZERO( &ss->fdSocket );
FD_SET( sockServer, &ss->fdSocket );
fd_set fdRead;
while( ss->isThreadRun )
{
FD_ZERO( &fdRead );
fdRead = ss->fdSocket;
int ret = select( 0, &fdRead, NULL, NULL, &tm );
if( SOCKET_ERROR == ret )
break;
for( u_int i = 0; i < (u_int)ss->fdSocket.fd_count; i++ )
{
if( FD_ISSET( ss->fdSocket.fd_array[i], &fdRead ) )
{
// 监听套节字接收到新连接
if( ss->fdSocket.fd_array[i] == sockServer )
{
// 最大连接数
if( ss->fdSocket.fd_count < FD_SETSIZE )
{
// 套接字部分
SOCKADDR_IN addrClient;
SOCKET sockClient = accept( sockServer, (SOCKADDR*)&addrClient, &len );
if( INVALID_SOCKET == sockClient )
continue;
FD_SET( sockClient, &ss->fdSocket );
if( ss->connectfunc != NULL )
{
(*(ss->connectfunc))( sockClient );
}
}
}
else
{
if( ss->procfunc != NULL && ss->recvsize > 0 )
{
char* rBuffer = new char[ss->recvsize];
ZeroMemory( rBuffer, ss->recvsize );
char* sBuffer = new char[ss->sendsize];
ZeroMemory( sBuffer, ss->sendsize );
UINT retSub = 0;
do
{
int ret = recv( ss->fdSocket.fd_array[i], rBuffer + retSub, ss->recvsize - retSub, 0 );
if( ret <= 0 )
{
if( ss->disconnectfunc != NULL )
{
(*(ss->disconnectfunc))( ss->fdSocket.fd_array[i] );
}
shutdown( ss->fdSocket.fd_array[i], SD_BOTH );
closesocket( ss->fdSocket.fd_array[i] );
FD_CLR( ss->fdSocket.fd_array[i], &ss->fdSocket );
retSub = 0;
break;
}
else
{
retSub += ret;
}
}
while( retSub < ss->recvsize && ss->isThreadRun );
if( retSub == 0 || !ss->isThreadRun )
{
delete [] rBuffer;
delete [] sBuffer;
continue;
}
UINT len = (*(ss->procfunc))( ss->fdSocket.fd_array[i], rBuffer, sBuffer );
if( len <= 0 || !ss->isThreadRun )
{
delete [] rBuffer;
delete [] sBuffer;
continue;
}
retSub = 0;
do
{
int ret = send( ss->fdSocket.fd_array[i], sBuffer + retSub, ss->sendsize - retSub, 0 );
if( ret <= 0 )
{
if( ss->disconnectfunc != NULL )
{
(*(ss->disconnectfunc))( ss->fdSocket.fd_array[i] );
}
shutdown( ss->fdSocket.fd_array[i], SD_BOTH );
closesocket( ss->fdSocket.fd_array[i] );
FD_CLR( ss->fdSocket.fd_array[i], &ss->fdSocket );
retSub = 0;
break;
}
else
{
retSub += ret;
}
}
while( retSub < ss->sendsize && ss->isThreadRun );
delete [] rBuffer;
delete [] sBuffer;
}
}
}
}
}
shutdown( sockServer, SD_BOTH );
closesocket( sockServer );
return 0;
}
DWORD WINAPI ThreadClientFunc( LPVOID lParam )
{
igfSocket* ss = (igfSocket*)lParam;
SOCKET sockClient = socket( AF_INET, SOCK_STREAM, 0 );
SOCKADDR_IN addrSrv;
addrSrv.sin_addr.S_un.S_addr = inet_addr( ss->ip );
addrSrv.sin_family = AF_INET;
addrSrv.sin_port = htons( ss->port );
FD_ZERO( &ss->fdSocket );
FD_SET( sockClient, &ss->fdSocket );
timeval tm;
tm.tv_sec = 1;
tm.tv_usec = 0;
fd_set set;
int error = -1;
int len = sizeof(int);
unsigned long ul = 1;
ioctlsocket( sockClient, FIONBIO, &ul ); // 设置为非阻塞模式
while( connect( sockClient, (SOCKADDR*)&addrSrv, sizeof(SOCKADDR) ) == -1 && ss->isThreadRun )
{
FD_ZERO( &set );
FD_SET( sockClient, &set );
if( select( (int)sockClient+1, NULL, &set, NULL, &tm ) > 0 )
{
getsockopt( sockClient, SOL_SOCKET, SO_ERROR, (char*)(&error), (int*)&len );
if( error == 0 )
break;
}
}
ul = 0;
ioctlsocket( sockClient, FIONBIO, &ul ); // 设置为阻塞模式
if( ss->connectfunc != NULL )
{
(*(ss->connectfunc))( sockClient );
}
while( ss->isThreadRun )
{
if( ss->procfunc != NULL && ss->recvsize > 0 )
{
char* rBuffer = new char[ss->recvsize];
ZeroMemory( rBuffer, ss->recvsize );
char* sBuffer = new char[ss->sendsize];
ZeroMemory( sBuffer, ss->sendsize );
UINT retSub = 0;
do
{
int ret = recv( sockClient, rBuffer + retSub, ss->recvsize - retSub, 0 );
if( ret <= 0 )
{
if( ss->disconnectfunc != NULL )
{
(*(ss->disconnectfunc))( sockClient );
}
shutdown( sockClient, SD_BOTH );
closesocket( sockClient );
//重新创建
sockClient = socket( AF_INET, SOCK_STREAM, 0 );
addrSrv.sin_addr.S_un.S_addr = inet_addr( ss->ip );
addrSrv.sin_family = AF_INET;
addrSrv.sin_port = htons( ss->port );
FD_ZERO( &ss->fdSocket );
FD_SET( sockClient, &ss->fdSocket );
timeval tm;
tm.tv_sec = 1;
tm.tv_usec = 0;
ul = 1;
ioctlsocket( sockClient, FIONBIO, &ul ); // 设置为非阻塞模式
while( connect( sockClient, (SOCKADDR*)&addrSrv, sizeof(SOCKADDR) ) == -1 && ss->isThreadRun )
{
FD_ZERO( &set );
FD_SET( sockClient, &set );
if( select( (int)sockClient+1, NULL, &set, NULL, &tm ) > 0 )
{
getsockopt( sockClient, SOL_SOCKET, SO_ERROR, (char*)(&error), (int*)&len );
if( error == 0 )
break;
}
}
ul = 0;
ioctlsocket( sockClient, FIONBIO, &ul ); // 设置为阻塞模式
if( ss->connectfunc != NULL && ss->isThreadRun )
{
(*(ss->connectfunc))( sockClient );
}
retSub = 0;
break;
}
else
{
retSub += ret;
}
}
while( retSub < ss->recvsize && ss->isThreadRun );
if( retSub == 0 || !ss->isThreadRun )
{
delete [] rBuffer;
delete [] sBuffer;
continue;
}
UINT len = (*(ss->procfunc))( sockClient, rBuffer, sBuffer );
if( len <= 0 || !ss->isThreadRun )
{
delete [] rBuffer;
delete [] sBuffer;
continue;
}
retSub = 0;
do
{
int ret = send( sockClient, sBuffer + retSub, ss->sendsize - retSub, 0 );
if( ret <= 0 )
{
if( ss->disconnectfunc != NULL )
{
(*(ss->disconnectfunc))( sockClient );
}
shutdown( sockClient, SD_BOTH );
closesocket( sockClient );
ul = 1;
ioctlsocket( sockClient, FIONBIO, &ul ); // 设置为非阻塞模式
while( connect( sockClient, (SOCKADDR*)&addrSrv, sizeof(SOCKADDR) ) == -1 && ss->isThreadRun )
{
FD_ZERO( &set );
FD_SET( sockClient, &set );
if( select( (int)sockClient+1, NULL, &set, NULL, &tm ) > 0 )
{
getsockopt( sockClient, SOL_SOCKET, SO_ERROR, (char*)(&error), (int*)&len );
if( error == 0 )
break;
}
}
ul = 0;
ioctlsocket( sockClient, FIONBIO, &ul ); // 设置为阻塞模式
if( ss->connectfunc != NULL && ss->isThreadRun )
{
(*(ss->connectfunc))( sockClient );
}
retSub = 0;
break;
}
else
{
retSub += ret;
}
}
while( retSub < ss->sendsize && ss->isThreadRun );
delete [] rBuffer;
delete [] sBuffer;
}
}
closesocket( sockClient );
return 0;
}
igfSocket::igfSocket( const char* ipaddr, UINT portid, UINT sendbuffersize, UINT recvbuffersize,
LPPROC pProc, LPCONNECT pConnect, LPDISCONNECT pDisconnect ) :
port( portid ), sendsize( sendbuffersize ), recvsize( recvbuffersize ),
procfunc( pProc ), connectfunc( pConnect ), disconnectfunc( pDisconnect )
{
strcpy_s( ip, 16, ipaddr );
isThreadRun = true;
if( strlen(ip) == 0 )
{
m_hThread = CreateThread( NULL, 0, ThreadServerFunc, (LPVOID)this, 0, NULL );
m_isServer = true;
}
else
{
m_hThread = CreateThread( NULL, 0, ThreadClientFunc, (LPVOID)this, 0, NULL );
m_isServer = false;
}
}
igfSocket::~igfSocket()
{
if(isThreadRun)
{
isThreadRun = false;
WaitForSingleObject( m_hThread, 10000 );
}
}
SOCKET igfSocket::IP2Socket( const char* ipaddr )
{
for( u_int i = 0; i < fdSocket.fd_count; i++ )
{
char ip[16];
if( igfSocket2IP( fdSocket.fd_array[i], ip ) )
{
if( strcmp( ipaddr, ip ) == 0 )
return fdSocket.fd_array[i];
}
}
return 0;
}
bool igfSocket::Send( SOCKET sock, const char* cSend, UINT len )
{
int ret = 0;
if( m_isServer )
{
ret = send( sock, cSend, len, 0 );
}
else
{
ret = send( fdSocket.fd_array[0], cSend, len, 0 );
}
return ( ret <= 0 ) ? false : true;
}
①导入socket文件
①头文件
#include "igfSocket.h"
//Socket
public:
igfSocket* server; //igfSocket指针对象
int m_port; //端口号
char * sendStr; //给flash发送的内容
void Init_socket(); //初始化Socket
void sendFlashMessage(char* pMsg);//给flash发送消息
①源文件:
Init_socket();
void CMFCAndFlashSocketTest02Dlg ::Init_socket()
{
m_port=6000;
if (igfInitSocket())
{
if (server)
{
server = new igfSocket("", m_port, sizeof(SHORT_IGF_MSG), sizeof(SHORT_IGF_MSG), OnProc, OnConnect, OnDisConnect);
}
}
else
{
MessageBox(L"创建套接字失败!");
}
}
vector<Client> ClientList;
UINT CALLBACK OnProc(SOCKET sock, char* cRecv, char* cSend)
{
//CMemorizingDlg* pThis = (CMemorizingDlg*)AfxGetApp()->GetMainWnd();
CMFCAndFlashSocketTest02Dlg* pThis = (CMFCAndFlashSocketTest02Dlg*)AfxGetApp()->GetMainWnd();
//Client client;
//pThis->ClientList.push_back(client);
//接受数据处理与显示
SHORT_IGF_MSG rcvMSG;
memset(&rcvMSG, 0, sizeof(SHORT_IGF_MSG));
memcpy_s(&rcvMSG, sizeof(SHORT_IGF_MSG), cRecv, sizeof(SHORT_IGF_MSG));
switch (rcvMSG.id)
{
case 3: //321 倒计时结束开始演示
{
TRACE("接受到了Flash发送的消息");
}
break;
}
return 0;
}
void CALLBACK OnConnect(SOCKET sock)
{
char ip[20] = { 0 };
igfSocket2IP(sock, ip);
Client client;
client.ip = ip;
client.sock = sock;
client.gameState = -1;
if (strcmp(ip, "127.0.0.1") == 0)
{
client.type = 1;
}
else
{
client.type = 0;
}
/*ClientList.push_back(client);*/
//AfxGetApp()->GetMainWnd()->GetDlgItem(IDD_MFCANDFLASHSOCKETTEST_DIALOG)-> ClientList.push_back(client);
//CMFCAndFlashSocketTestDlg *pThis=(CMFCAndFlashSocketTestDlg *) AfxGetApp();
ClientList.push_back(client);
}
void CALLBACK OnDisConnect(SOCKET sock)
{
CMFCAndFlashSocketTest02Dlg* pThis = (CMFCAndFlashSocketTest02Dlg*)AfxGetApp()->GetMainWnd();
for (unsigned int i = 0; i < ClientList.size(); i++)
{
if (ClientList[i].sock == sock)
{
ClientList.erase(ClientList.begin() + i);
}
}
// pThis->returnStandby();
}
void CMFCAndFlashSocketTest02Dlg::sendFlashMessage(char* pMsg)
{
for (unsigned int m = 0; m < ClientList.size(); m++)
{
if (ClientList.at(m).type == 1)
{
server->Send(ClientList[m].sock, pMsg, strlen(pMsg));
}
}
}
①添加案件检测:
BOOL CMFCAndFlashSocketTest02Dlg::PreTranslateMessage(MSG* pMsg)
{
// TODO: 在此添加专用代码和/或调用基类
if (pMsg->message==WM_KEYUP)
{
switch(pMsg->wParam)
{
case 0+48:
sendStr = "choose";
sendFlashMessage(sendStr);
break;
}
}
return CDialogEx::PreTranslateMessage(pMsg);
}
①添加摧毁事件
void CMFCAndFlashSocketTest02Dlg::OnDestroy()
{
CDialogEx::OnDestroy();
// TODO: 在此处添加消息处理程序代码
if (server != NULL)
{
igfUnInitSocket();
delete server;
server = NULL;
}
ClientList.clear();
}