标题：飞秋工作室
简介
其实，这也就是软件的模块化，方便开发和维护，同时，对用户的需求和可以灵活的满足。针对飞秋的话应该就是，插件化，将成体功能拆分成若干插件，这样就可以在功能和体积上取得平衡点。也减轻了开发者的工作量和开发难度。
发展
该工作室从最初的飞鸽传书软件发展成飞秋软件，经过数年时间就把软件做的非常具有影响力，单位严禁上网，同事们工作之余的娱乐就变得很单调，大多都是用来玩一些单机版的小游戏，或者看影视剧，都是从家中下载了拷贝过来，在局域网内的即时通讯工具“飞秋”上飞来飞去的相互传阅。前段日子有人飞给我一部耿乐和宋佳主演的《跟我的前妻谈恋爱》，并郑重叮嘱一定要看看，说是这片子可好了。我喜欢电影，但极少看电视剧，是以对耿乐没什么印象，倒是知道宋佳，因为《闯关东》，因为一个由她塑造的令人心疼的悲剧人物鲜儿。今日周末，又赶上阴雨连绵无法外出，想起同事那别有意味郑重推荐的样子，就窝在家中日以继夜地直至把这部电视剧看完，没想到竟被感动了个稀里哗啦。这应该算是一部都市情感喜剧，故事情节紧凑，演员的表演都很到位，耿乐的表演尤为出色，主人公马勇的情感历程跌宕起伏，剧情不时令人捧腹，在诙谐中诠释着婚姻与爱情，高潮部分过渡自然，马勇独自坐于路边恸哭直至被警察误解的一幕尤为令人回肠荡气，不刻意煽情，却令人忍不住笑，甚至忍不住泪。结局是圆满的，虽然带有一定的迎合“主旋律与和谐社会”的因素，但这不妨碍你看过之后在心中回荡的那份温情。只是，电视剧只是电视剧而已，美好的结局往往是作者的理想主义，虽然作品中的悲剧都成了喜剧，却恰恰昭示了现实生活中的许多无奈：这世间令人心痛的往往不是悲剧，而是悲剧的无法化解。
FreeEIM
作为局域网聊天软件 FreeEIM 跟飞秋是不一样的，他完全由自己开发，飞秋工作室做开发的飞秋，是参考飞鸽传书的传书协议，他与飞鸽传书是可以共同使用的，具有兼容性，而FreeEIM使用的是自主开发的协议，所以不能与飞鸽传书一起使用，两者可以并存，互不干扰。关于飞秋的跨网段通信的问题，昨天试了下如果两台计算机都在路由器后面的话，就是说这两台电脑都是通过路由器上公网，而每个路由器下面又有好多台计算机，我从“加其他网段好友”这个功能里加了相应的路由器的IP就可以加这个下面的在线好友了，它怎么能加为好友，又怎么能知道信息该发给谁呢，这是怎么实现的呢，哪位大哥能给解释下它的原理呢，非常感谢？
原理
局域网的资源丰富，使用Windows共享机制可以很方便的访问大家的共享文件。但你能搜索到和你不同网段的资源么。不行。那么使用其他的软件（非跨网段专用通讯软件）能相互通讯么？不能。这是为什么呢？因为局域网中也使用TCP/IP协议，而TCP/IP协议中常用的基础协议TCP和UDP都使用子网掩码这个东东。所以如果你们的子网不是相互包含，那么你们通讯时所发送的数据包将被无情的丢弃。那我用广播通讯不行么？ 当然行啦，不过广播通信会增加其他非参与者的负荷。如果使用多播，多播通讯编程难么？ 我原来也以为很难，呵呵，现在我可不那么认为了，下面是多播通讯类的代码。
//Multicast.c
#pragma once
// auth: YYcYY
// date: 2006-8-12
// copyright: All free
//定义收到数据时通知父窗口的消息编号：WM_MUC_RECEIVE_DATA
#define WM_MUC_RECEIVE_DATA (WM_USER + 1097)
#define MAX_MUC_PACKET_SIZE 1460
#define SEND_BUFF_COUNT 4
#define RECEIVE_BUFF_COUNT 32
#define MU_PORT 5201
#define MU_GROUP_IP "224.0.0.8"
const int PACKET_HEAD_SIZE = 20;
#define MSG_TYPE_ALLUSER 1
#define MSG_TYPE_ACK 2
#define MSG_TYPE_ONLINE 3
#define MSG_TYPE_PROXY_REQUEST 4 //特殊用途#define MSG_TYPE_ONEUSER 5
struct SPACKET 
{
char used;
char nType;
long long time;
int nUnused;
char data[MAX_MUC_PACKET_SIZE-20];
};
// CMulticast 命令目标
class CMulticast : public CAsyncSocket
{
private:
CWnd * m_pParent;
SOCKADDR_IN m_GroupAddr;
ip_mreq m_mrMReq;
int m_nTTL;
CString m_sLocalIP; 
public:
CMulticast(CWnd * pParent, CString & localIP);
virtual ~CMulticast();
virtual void OnReceive(int nErrorCode);
BOOL InitSock(void);
void DeleteThis();
int SendData(int nIndex, int len);
SPACKET SendBuff[SEND_BUFF_COUNT];
SPACKET ReveiveBuff[RECEIVE_BUFF_COUNT];
SPACKET AckBuff;
};
// Multicast.cpp : 实现文件
//
#include "stdafx.h"
#include "Multicast.h"
#include ".\multicast.h"
// CMulticast
CMulticast::CMulticast(CWnd * pParent, CString & localIP)
{
m_pParent = pParent;
m_sLocalIP = localIP; //如果不设置请使用空字符串
m_nTTL = 3; //允许经过的路由个数
// 初试化个个成员变量
memset(&m_mrMReq, 0, sizeof(m_mrMReq));
memset(&m_GroupAddr, 0, sizeof(m_GroupAddr));
memset(ReveiveBuff, 0, sizeof(SPACKET)* RECEIVE_BUFF_COUNT);
memset(SendBuff, 0, sizeof(SPACKET)* SEND_BUFF_COUNT);
// 使用函数初始化 否则容易产生内存错误
InitSock();
}
CMulticast::~CMulticast()
{
// 使用函数析构 否则容易产生内存错误
DeleteThis();
}
void CMulticast::DeleteThis()
{
// 离开多播组
setsockopt (m_hSocket, IPPROTO_IP, IP_DROP_MEMBERSHIP, (char FAR *)&m_mrMReq, sizeof(m_mrMReq));
}
// CMulticast 成员函数
void CMulticast::OnReceive(int nErrorCode)
{
// TODO: 在此添加专用代码和/或调用基类
int i=0,len=0;
UINT nPort = 0;
CString * pStr = new CString; // 由使用者使用完后释放。
for (i=0;i<RECEIVE_BUFF_COUNT;i++)
{
if (ReveiveBuff[i].used == 0)
{
break;
}
}
len = ReceiveFrom(&ReveiveBuff[i], MAX_MUC_PACKET_SIZE, *pStr, nPort);
if (len > 0)
{ //通知父窗口，消息第一个参数 i 为接收到的消息在缓冲区的索引值
::PostMessage(m_pParent->GetSafeHwnd(), WM_MUC_RECEIVE_DATA, (WPARAM)i, (LPARAM)pStr);
}
CAsyncSocket::OnReceive(nErrorCode);
}
BOOL CMulticast::InitSock(void)
{ //创建 Socket 并绑定地址为 m_sLocalIP
if(!Create(MU_PORT, SOCK_DGRAM, FD_READ,m_sLocalIP))
return FALSE; 
BOOL bMultipleApps = TRUE; /* 允许复用端口*/
SetSockOpt(SO_REUSEADDR, (void*)&bMultipleApps, sizeof(BOOL), SOL_SOCKET);
/* 填写 m_GroupAddr 的字段值 */
memset(&m_GroupAddr, 0, sizeof(m_GroupAddr));
m_GroupAddr.sin_family = AF_INET;
m_GroupAddr.sin_addr.s_addr = inet_addr(MU_GROUP_IP);
m_GroupAddr.sin_port = htons((USHORT)MU_PORT);
/* 加入多播组 */
m_mrMReq.imr_multiaddr.s_addr = inet_addr(MU_GROUP_IP); /* 多播组地址 */ 
m_mrMReq.imr_interface.s_addr = inet_addr(m_sLocalIP); /* 要使用的本地地址，需要与 绑定的地址相同*/ 
if(setsockopt(m_hSocket, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char FAR *)&m_mrMReq, sizeof(m_mrMReq)) < 0)
return FALSE;
/* 设置 TTL 值，与跨越的路由设备个数相关，一般不要设置太大 1-127 */
if(SetSockOpt(IP_MULTICAST_TTL, &m_nTTL, sizeof(int), IPPROTO_IP) == 0)
return FALSE; /* 设置 TTL 发生错误 */
return TRUE;
}
int CMulticast::SendData(int nIndex, int len)
{ 
if (nIndex == -1)
{ // 发送确认数据 
return SendTo(&AckBuff, len, MU_PORT, MU_GROUP_IP); 
}
if (nIndex >= SEND_BUFF_COUNT || nIndex < 0)
{
return 0;
}
return SendTo(&SendBuff[nIndex], len, MU_PORT, MU_GROUP_IP); 
}
使用这个多播类，就想使用一般的UDP套接字一样。
发送数据 默认使用 索引为0的缓冲区
SPACKET * pak = &m_pMuSock->SendBuff[0];
int len = str.GetLength();
pak->used = 1;
pak->nType = MSG_TYPE_ONEUSER;
pak->nUnused = 0;
pak->time= CTime::GetCurrentTime().GetTime();
strncpy(pak->data, str, len);
pak->data[len] = 0;
pak->nUnused = inet_addr(*pStr);
m_pMuSock->SendData(i, len + PACKET_HEAD_SIZE +1); 
接收数据 在 DefWindowProc(UINT message, WPARAM wParam, LPARAM lParam) 中添加
LRESULT CTestDlg::DefWindowProc(UINT message, WPARAM wParam, LPARAM lParam)
{
// TODO: 在此添加专用代码和/或调用基类
SPACKET * pak;
CString * psIP; 
switch(message)
{
case WM_MUC_RECEIVE_DATA: 
pak = &m_pMuSock->ReveiveBuff[wParam];
psIP = (CString *)lParam;
case WM_MUC_RECEIVE_DATA: 
pak = &m_pMuSock->ReveiveBuff[wParam];
psIP = (CString *)lParam;
if (pak->nType == MSG_TYPE_ALLUSER)
{
//处理消息 
}
delete psIP;
pak->used = 0;
break;
}