深入解析IPMSG飞鸽传书C++源代码

本文还有配套的精品资源,点击获取 menu-r.4af5f7ec.gif

简介:IPMSG是一款允许局域网内即时通讯和文件传输的开源通信软件。源代码压缩包"ipmsg206src.rar"提供了一个研究网络协议、多线程和C++编程的宝贵机会。本源代码通过实现UDP协议进行消息的发送与接收,包括网络通信、数据包解析、多线程处理、用户界面设计和文件传输等关键模块。通过深入分析和理解这些模块,学习者将能够提升网络编程技能,了解多线程和UI设计等核心概念,并优化程序性能。 ipmsg206src.rar飞鸽传书C++源代码

1. IPMSG通信软件简介

在现代社会,即时通讯软件已成为个人和企业沟通不可或缺的工具。IPMSG,作为一种广泛使用的通信软件,它不仅提供了即时消息传递的基本功能,还支持多种扩展功能,如文件共享、远程协助等。IPMSG软件的设计目标是为用户提供一个稳定、高效且用户友好的通信平台。

IPMSG的开发始于对传统即时通讯软件的反思,它注重于用户隐私和数据安全性,因此采用端到端的加密技术。同时,为了应对大数据量传输,IPMSG使用了高效的UDP协议进行数据传输,这在减少延迟的同时提高了数据传输的速度。

在这一章中,我们将探究IPMSG的设计理念和基本架构,并对其关键技术进行初步了解。这将为我们后续深入探讨IPMSG的工作原理和技术细节打下坚实的基础。

2. UDP协议工作原理及应用

2.1 UDP协议基础

2.1.1 UDP协议的特点与应用场景

用户数据报协议(UDP)是Internet协议套件的一个无连接的传输层协议,提供了一个简单而不可靠的传输方式。UDP协议的特点包括:

  • 无连接 :发送数据之前不需要建立连接,从而减少了通信过程的延迟。
  • 数据报大小固定 :一个UDP数据报最大为65535字节,包括头部和数据。
  • 效率高 :无须建立连接,因此在传输大量数据的场合,如视频或音频会议,效率较高。
  • 不可靠 :不保证数据包的交付、顺序和完整性。
  • 无拥塞控制 :可能造成网络拥堵。
  • 资源需求低 :对系统资源的要求低,适用于资源受限的设备,如物联网设备。

UDP的特点使得它特别适合以下应用场景:

  • 实时应用:如VoIP电话、在线游戏、视频会议等,这些应用通常容忍一定程度的数据丢失,但需要低延迟。
  • 广播或多播传输:在多点传输时,UDP可以向多个目的地发送相同的数据包。
  • DNS查询:域名系统广泛使用UDP,因为它允许快速的小查询响应。
  • SNMP(简单网络管理协议):用于远程监控网络设备。

2.1.2 UDP数据报结构解析

UDP数据报由头部和数据两部分组成,其结构如图2.1所示:

  ***
+--------+--------+--------+--------+
|     Source Port     |   Dest Port   |
+--------+--------+--------+--------+
|            Length           |   Checksum   |
+--------+--------+--------+--------+
|                                   |
|                Data              |
|                                   |
+-----------------------------------+

图2.1 UDP数据报结构图

  • 源端口(Source Port) :可选字段,表示发送数据的应用程序端口号。
  • 目的端口(Destination Port) :接收数据的应用程序端口号。
  • 长度(Length) :UDP头部和数据的总长度,单位为字节。
  • 校验和(Checksum) :用于错误检测,该字段是可选的,但在DNS查询中常用。

数据部分的内容由应用层程序决定。

2.2 UDP在IPMSG中的应用

2.2.1 IPMSG软件对UDP的选择理由

IPMSG是一款使用UDP协议实现即时消息通信的软件。以下是IPMSG选择UDP的几个主要原因:

  • 低延迟 :即时消息通信需要快速响应,UDP的无连接特性满足此需求。
  • 简单实现 :对于开发者而言,UDP编程相对简单,易于实现和维护。
  • 资源消耗少 :对于轻量级应用,UDP消耗较少的系统资源,对于长连接应用来说更为高效。

2.2.2 UDP通信流程及其在IPMSG中的实现

IPMSG软件中的UDP通信流程主要包括以下几个步骤:

  1. 监听端口 :IPMSG首先监听一个特定的端口,准备接收客户端的连接请求。
  2. 接收数据 :一旦客户端发送消息,IPMSG通过接收函数读取数据报。
  3. 处理数据 :收到数据报后,IPMSG解析数据包,然后根据数据报的内容执行相应的操作。
  4. 发送响应 :如果需要,IPMSG会构造一个新的UDP数据报,将响应发送回客户端。

在IPMSG中,UDP通信流程的实现涉及到网络编程技术,具体代码示例如下:

#include <iostream>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#include <unistd.h>

int main() {
    // 创建UDP socket
    int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
    if (sockfd < 0) {
        std::cerr << "Error creating socket" << std::endl;
        return 1;
    }
    // 定义服务器地址结构体
    struct sockaddr_in serv_addr;
    memset(&serv_addr, 0, sizeof(serv_addr));
    serv_addr.sin_family = AF_INET;
    serv_addr.sin_port = htons(12345); // 设置端口号
    serv_addr.sin_addr.s_addr = inet_addr("***.*.*.*"); // 设置IP地址

    // 绑定socket到服务器地址
    if (bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) {
        std::cerr << "Error on binding" << std::endl;
        close(sockfd);
        return 1;
    }

    while (true) {
        char buffer[1024];
        struct sockaddr_in cli_addr;
        socklen_t len = sizeof(cli_addr);
        // 接收数据
        int n = recvfrom(sockfd, buffer, sizeof(buffer), 0, (struct sockaddr *) &cli_addr, &len);
        buffer[n] = '\0'; // 添加字符串结束符

        std::cout << "Received message: " << buffer << std::endl;

        // 发送响应
        std::string response = "Message received";
        sendto(sockfd, response.c_str(), response.size(), 0, (struct sockaddr *) &cli_addr, len);
    }
    close(sockfd);
    return 0;
}

此代码段展示了IPMSG软件的UDP通信流程。在实际应用中,IPMSG会根据具体需求处理接收到的消息,并可能对消息进行进一步的转发或存储操作。

上述代码仅作为示例,用于说明IPMSG软件中UDP通信的实现原理。在实际开发中,还需要考虑安全性、异常处理、以及错误检查等其他因素。

3. 网络通信模块实现与数据包解析

网络通信模块是IPMSG软件的核心部分之一,它负责处理所有的数据传输工作。要深入了解该模块的实现,首先需要从它的设计开始着手。

3.1 网络通信模块的设计

3.1.1 模块结构与功能划分

网络通信模块主要负责网络连接的建立、维护以及数据的发送和接收。具体到功能划分上,可以分为以下几个子模块:

  1. 连接管理模块 :负责监听端口,接受连接请求,并建立客户端与服务端之间的通信。
  2. 数据传输模块 :确保数据包的有效传输,包括数据的打包、发送、接收和确认。
  3. 超时与重传机制 :当网络不稳定时,负责处理丢包情况,实现数据包的超时检测和必要时的重传功能。
  4. 协议处理模块 :对通信协议进行解析,确保IPMSG的通信按照特定协议进行。

3.1.2 网络事件处理与I/O模型选择

在处理网络通信时,需要有效地处理各种网络事件,如连接到来、数据到达、异常发生等。为了高效处理这些事件,正确的I/O模型的选择至关重要。

在Linux系统下,常用I/O模型主要有:

  • 阻塞I/O模型 :在执行I/O操作时,会阻塞当前线程直到操作完成。
  • 非阻塞I/O模型 :I/O操作不会阻塞线程,需要轮询检查操作是否完成。
  • I/O复用模型 :通过select/poll/epoll等机制,可监视多个文件描述符,有事件发生时才处理,提高效率。
  • 信号驱动I/O模型 :设置信号处理函数,在I/O事件发生时产生信号通知应用程序。
  • 异步I/O模型 :I/O操作开始后,由内核完成整个I/O操作,完成后通知应用程序。

对于IPMSG这样的应用来说,事件驱动的I/O复用模型(如epoll)是最合适的选择,因为它能够在不增加过多线程的情况下,同时处理多个连接,提高效率。

3.2 数据包解析模块的构建

数据包解析是网络通信的基础,正确解析数据包是实现稳定通信的关键。

3.2.1 数据包格式与解析流程

IPMSG的数据包格式遵循自定义的协议,例如包括起始标志、协议类型、数据长度、校验码等字段。数据包解析流程大致如下:

  1. 数据包接收 :从网络接口接收数据包。
  2. 数据包验证 :检查数据包的起始标志和校验码,确保数据包的完整性和正确性。
  3. 数据包解析 :根据协议格式,分离出协议类型、数据长度等信息,并提取有效载荷。
  4. 数据包校验 :执行更复杂的校验机制(如CRC校验),确保数据包未被篡改。
  5. 数据包处理 :根据协议类型,将数据包分发到相应的模块或服务中进行处理。

3.2.2 解析算法与性能优化

性能优化是数据包解析中的一个关键方面,可以采取以下措施:

  1. 缓冲管理 :合理分配和使用缓冲区,避免频繁的内存分配和释放。
  2. 多级缓存 :对于解析过程,采用多级缓存策略,减少内存访问次数和提高缓存命中率。
  3. 并行处理 :对于可以并行的解析任务,使用多线程或者异步机制并行处理,提高解析速度。
  4. 预处理 :对一些频繁出现的数据和模式进行预处理和缓存,减少解析时的计算量。

下面的伪代码展示了上述解析算法的一个实现:

struct PacketHeader {
    uint8_t start_flag;
    uint8_t protocol_type;
    uint16_t data_length;
    uint32_t checksum;
};

void parsePacket(char *buffer, size_t length) {
    PacketHeader header;
    memcpy(&header, buffer, sizeof(header));
    // 验证起始标志和校验码
    if (header.start_flag != EXPECTED_FLAG || !isValidChecksum(buffer, length, header.checksum)) {
        handleInvalidPacket(buffer, length);
        return;
    }

    // 根据协议类型进行不同的处理
    switch(header.protocol_type) {
        case TYPE_1:
            processType1(buffer + sizeof(header), header.data_length);
            break;
        case TYPE_2:
            processType2(buffer + sizeof(header), header.data_length);
            break;
        // 更多类型处理...
        default:
            handleUnknownType(buffer, length);
            break;
    }
}

bool isValidChecksum(char *buffer, size_t length, uint32_t expected_checksum) {
    // 实现校验逻辑
    // ...
    return true;
}

总结

通过本章节的介绍,我们详细了解了IPMSG通信软件中的网络通信模块和数据包解析模块的构建。在下一章中,我们将深入探讨多线程编程技术如何在IPMSG中实现应用。

4. 多线程编程技术在IPMSG中的应用

4.1 多线程编程基础

4.1.1 线程的创建和同步机制

在现代操作系统中,多线程编程是实现并发和提升应用性能的关键技术。线程,作为轻量级的进程,能够共享进程资源,但也引入了对共享资源访问的同步需求。在多线程编程中,线程的创建、终止以及同步机制显得尤为重要。

在C++11标准中,提供了对多线程编程的支持,包括线程的创建和基本的同步原语。使用 std::thread 可以创建新线程,每个线程可以执行一个函数或者可调用对象。在IPMSG中,通信模块和界面模块等多个部分会分别运行在不同的线程中,以提高响应速度和用户交互体验。

同步机制主要包括互斥锁(mutex)、条件变量(condition_variable)以及原子操作(atomic operations)。互斥锁用于保证资源访问的互斥性,防止多个线程同时修改同一个资源导致数据不一致的问题。条件变量提供了线程间通信的机制,当某个线程需要等待一个条件成立时,可以使用条件变量进行等待。

#include <thread>
#include <mutex>
#include <condition_variable>
#include <iostream>

std::mutex mtx;
std::condition_variable cv;

bool ready = false;

void print_id(int id) {
    std::unique_lock<std::mutex> lck(mtx);
    while (!ready) {
        cv.wait(lck);
    }
    // 打印某个线程的ID。
    std::cout << "Thread " << id << '\n';
}

void go() {
    std::unique_lock<std::mutex> lck(mtx);
    ready = true;
    cv.notify_all();
}

int main() {
    std::thread threads[10];
    // 创建10个线程。
    for (int i = 0; i < 10; ++i)
        threads[i] = std::thread(print_id, i);

    std::cout << "10个线程正在等待...\n";
    go();                  // 主线程释放所有线程。
    for (auto& th : threads)
        th.join();

    std::cout << "所有线程已完成。\n";
    return 0;
}

在上面的代码示例中,通过 std::thread 创建了10个线程,每个线程执行 print_id 函数。主线程通过设置 ready true 并调用 cv.notify_all() 来通知所有等待线程继续执行。这是使用互斥锁和条件变量进行线程间同步的一个典型例子。

4.1.2 线程池技术及其在IPMSG中的应用

线程池技术是一种资源复用技术,通过维护一定数量的工作线程,以减少线程的频繁创建和销毁带来的性能开销。线程池中的线程通常处于等待任务到来的状态,一旦有任务到来,就从空闲线程中取出一个处理任务。

在IPMSG中,线程池技术能够有效管理通信模块中的大量并发操作。比如在处理大量消息发送和接收时,线程池能够保证系统资源的有效利用,同时避免了因为并发量大而导致的频繁创建和销毁线程。

线程池通常包括任务队列、线程集合、同步机制等组件。任务队列负责存储待执行的任务,线程集合则按照一定的策略从任务队列中获取任务执行。同步机制用于保证线程安全,避免任务执行过程中的竞争条件。

4.2 多线程在通信模块中的实践

4.2.1 多线程下的数据接收与处理

在IPMSG通信软件中,多线程技术主要应用于网络通信模块,其中一个典型的应用场景是数据的接收与处理。由于网络I/O操作通常涉及到阻塞调用,单线程的处理方式无法做到良好的用户体验和高效率的数据处理。

在多线程环境下,主线程可以持续监听网络事件,一旦有新的数据包到来,就将数据包读取任务提交到线程池中。这些任务可以被多个工作线程并行处理,实现数据包的快速接收和响应。

void processPacket(std::shared_ptr<Packet> packet) {
    // 处理数据包的逻辑
    // ...
}

void listenForPackets() {
    std::thread listener([]() {
        while (true) {
            // 阻塞等待数据包到来
            std::shared_ptr<Packet> packet = waitForPacket();
            // 将处理数据包的任务提交到线程池
            ThreadPool::getInstance().enqueue(std::bind(processPacket, packet));
        }
    });
    listener.detach();
}

在这个示例中, waitForPacket() 函数表示阻塞等待数据包到来。一旦数据包到达,就创建一个 Packet 对象,并将其包装在一个 std::shared_ptr 中,然后将任务交给线程池处理。 ThreadPool 是一个典型的线程池实现,它能够管理一组线程,并提供任务提交的接口。

4.2.2 线程安全与性能平衡策略

在多线程编程中,线程安全是一个至关重要的考虑因素。线程安全涉及到多个线程在访问共享资源时能够避免数据竞争和条件竞争。在IPMSG通信软件中,线程安全问题主要出现在处理消息发送、接收缓存管理等方面。

为保证线程安全,可以采用互斥锁、原子操作、读写锁等同步机制。然而,过度使用同步机制也会引入性能开销,因此需要在保证线程安全和提高性能之间进行权衡。常见的策略包括:

  • 减少锁的粒度:尽量避免大范围的临界区,以减少线程等待时间。
  • 使用无锁编程:利用原子操作代替锁,提高并发处理性能。
  • 读写锁分离:对于读多写少的场景,使用读写锁可以提高并发读取的性能。
std::shared_mutex rw_mutex;

void readData() {
    std::shared_lock<std::shared_mutex> lock(rw_mutex);
    // 执行数据读取操作
}

void writeData() {
    std::unique_lock<std::shared_mutex> lock(rw_mutex);
    // 执行数据写入操作
}

在上面的代码示例中, std::shared_mutex 是C++17提供的读写锁实现。使用 shared_lock 来对共享资源进行读操作,允许多个线程同时读取。对于写操作,则使用 unique_lock 来保证互斥访问。通过这种方式,能够有效地提升读操作的并发性能,同时保证写操作的线程安全。

在设计和实现IPMSG的多线程通信模块时,需要细致地分析并采用这些策略来达到最优的性能和稳定性。通过合理的设计,可以确保在高负载下通信模块的高效运行,从而为用户提供稳定可靠的即时消息服务。

5. 用户界面模块设计与文件传输功能实现

用户界面模块是任何软件产品面向用户的直接表现形式,其设计好坏直接影响用户体验。同时,文件传输作为IPMSG软件的核心功能之一,其设计与实现细节对于确保数据传输的稳定性和高效性至关重要。

5.1 用户界面模块的设计原则

5.1.1 模块架构与用户交互设计

用户界面模块设计的首要原则是简洁性和直观性。一个好的用户界面应该让新用户在不阅读说明书的情况下也能迅速上手。因此,在设计界面架构时,应该遵循清晰的布局和逻辑流程,将最常用的功能放在显眼的位置,减少用户的认知负担。

用户交互设计方面,则需要保证操作的直观性和反馈的及时性。例如,当用户点击发送文件按钮时,界面上应立即显示文件正在发送的提示,文件发送成功或失败后,应有明确的反馈信息告知用户结果。交互设计还需要关注用户体验的连贯性,即用户在界面上的任何操作都应有预期的结果。

5.1.2 界面美观与操作便捷性的权衡

在界面美观与操作便捷性之间进行权衡是一项挑战。一方面,美观的界面能够吸引用户,提升软件的总体形象;另一方面,操作便捷是提高用户效率的关键。因此,在设计界面时,应确保视觉效果与用户体验之间的平衡。

例如,可以利用现代UI设计趋势如扁平化、卡片式布局等,在不影响功能的前提下提高界面的视觉吸引力。同时,对于常用功能,如联系人列表、消息框等,应设计成易于访问和操作的组件,减少鼠标或触摸屏操作的步数,加快用户的操作速度。

5.2 文件传输功能的实现细节

5.2.1 文件传输协议的选择与设计

文件传输功能需要一种可靠且高效的协议来确保数据的完整性和传输的快速性。IPMSG在实现文件传输时,可以选择适合小文件传输的TCP协议,或者适合大文件和长距离传输的UDP协议。考虑到IPMSG的即时通信特性,一般会选择TCP协议,因为它提供了可靠的连接和数据流的有序传输。

在设计文件传输协议时,还需要考虑到协议的封装和解封装过程。例如,文件数据在发送前会被封装在一个特定的数据包中,这个数据包会包含文件的元数据,如文件名、大小和类型等,以及文件数据本身。接收端在接收到数据包后,需要按照协议规定的格式进行解封装,提取文件数据并进行后续处理。

5.2.2 文件传输过程中的错误处理与用户反馈

在文件传输过程中,可能会遇到网络中断、文件损坏或传输超时等问题。因此,软件应实现一个健壮的错误处理机制,并提供清晰的用户反馈。错误处理机制应当记录错误发生时的详细信息,例如错误类型、发生时间等,并尝试进行错误恢复,比如重新传输失败的文件部分。

用户反馈机制则需要及时告知用户传输状态,无论是成功还是失败。如果传输失败,应给出可能的原因和解决方案,例如建议用户检查网络连接,或提供重试的选项。

在实现文件传输功能时,可以考虑使用现有库或框架来处理文件的发送和接收操作,这样可以减少开发工作量,并利用已有技术的稳定性。当然,在此基础上,还需要对这些操作进行优化和定制,以满足IPMSG软件的特定需求和特性。

通过结合以上设计原则和实现细节,IPMSG的用户界面模块和文件传输功能不仅能够提供良好的用户体验,还能够确保数据传输的可靠性与高效性。

本文还有配套的精品资源,点击获取 menu-r.4af5f7ec.gif

简介:IPMSG是一款允许局域网内即时通讯和文件传输的开源通信软件。源代码压缩包"ipmsg206src.rar"提供了一个研究网络协议、多线程和C++编程的宝贵机会。本源代码通过实现UDP协议进行消息的发送与接收,包括网络通信、数据包解析、多线程处理、用户界面设计和文件传输等关键模块。通过深入分析和理解这些模块,学习者将能够提升网络编程技能,了解多线程和UI设计等核心概念,并优化程序性能。

本文还有配套的精品资源,点击获取 menu-r.4af5f7ec.gif

软件简介   飞鸽传书(IP Messenger),是由日本人Shirouzu Hiroaki (白水 启章)所发明的免费软件, 是一款局域网内即时通信软件,基于 TCP/IP(UDP)。可运行于多种操作平台(Win/Mac/UNIX/Java),并实现跨平台信息交流。不需要服务器支持, 支持文件/文件夹的传送 (2.00版以上),通讯数据采用 RSA/Blofish 加密 (2.00版以上),十分小巧,简单易用,而且你可以完全免费使用它。目前已有的版本包括: Win32, Win16, MacOS, MacOSX, X11, GTK, GNOME,Java 等, 并且公开源代码. 系统要求   Microsoft Windows 95/98/Me/NT4.0/2000/XP/2003   95/98/NT4.0 ... 要求 comctl32.dll(公共控件) 的版本为 5.x 或更高.   (如果你安装的 IE 是 5.x 或更高版本, 那么就不必担心这个问题了)   注意: Windows 3.1(和 NT3.5x), 请使用 IP Messenger for Win16. 使用说明   < 安装/卸载 >   执行 setup.exe 你可以将 IPMsg 安装到指定目录, 或者重新注册到启动组.   如果需要删除 IPMsg, 请先从控制面板中卸载, 再手动删除 IPMsg 目录.   < 系统托盘区图标 >   左键双击图标, 即可打开发送消息窗口.   右键点击图标, 可进入 [服务设置], [离开] 等.   < 发送消息窗口 >   - 发送消息时, 若勾选了 [封装], 则接收者要先打开信封才能看到消息,   如果你还勾选了 [上锁], 则接收者在打开信封时还需要输入密码.   (密码是由接收者自己在 [服务设置] 中设置的)   - 若要发送文件/文件夹, 可直接将文件/文件夹拖入发送消息窗口   或在发送消息窗口上点击右键, 再选择发送文件或发送文件夹   - 传送文件/文件夹时, 当接收者还没有保存(下载)文件/文件夹时,   若发送者关闭或重启了 IPMsg, 则附带的文件信息将被清除,   接收者将不能继续接收(下载)到此文件.   - 用户列表前缀符号说明   ":" 表示用户处于离开模式.   "|" 表示用户使用的不是 2.0 以上版本的 IPMsg,   将不支持文件/文件夹的传送, 并且不支持通信数据加密.   "|"(短线) 表示只支持文件/文件夹的传送.   - 拖动列表表头标题项可改变其顺序, 并可点击右键选择"保存列表顺序"   - 在消息输入窗口中, 可使用 Ctrl+Tab 输入制表符 Tab.   - 在发送消息窗口上点击右键, 可以进入设置显示优先级, 选择工作组,   搜索用户(Ctrl+F), 传送文件, 传送文件夹, 保存列表顺序, 字体设置,   窗口大小设置, 固定窗口位置, 列表显示设置.   - 在用户名上点击右键, 可设置其显示优先级   优先级按由小到大的顺序排序   - 通过设置显示优先级, 可将经常联系的用户至于列表顶端,   或者隐藏不需要联系的用户   < 接收消息窗口 >   - 在接收消息窗口上点击右键, 可以进入字体设置,   窗口大小设置, 固定窗口位置.   - 接收消息窗口标题栏中的 "+" 或 "-" 表示通信数据使用了加密算法   "+" 表示 RSA/1024 位, blowfish/128 位加密   "-" 表示 RSA/512 位, RC2/40 位加密   - 如果你收到的消息附带了文件, 将会显示出附件按钮.   点击按钮即可保存文件.   < 其他 >   - 如果需要(通过路由器)连接到广域网, 则需要设置广播地址.   详见广域网设置(广播设置)   - 其它功能都很容易理解, 你试一试就明白了 操作技巧   1、隐藏/显示窗口Ctrl+D   2、按住Ctrl键再点[刷新]可保持现有用户,搜索新上线的用户   3、打开发送/接收消息窗口Ctrl+Alt+S/R(需要进行详细设置)   4、打开搜索窗口Ctrl+F   5、接收到多个文件,保存时可勾选[全部] 软件原理   局域网聊天软件飞鸽传书是目前比较流行的局域网即时通讯软件,由于历史悠久,它具有比较多的用户。 因为 FreeEIM 的实现原理和飞鸽传书差不多,希望广大用户了解其原理后,在使用时更加得心应手。   开发多年的飞鸽,在他的基础上增加了些许功能,例如语音对话,这里继续讨论FreeEIM(飞鸽传书),前几天,详细的了解了FreeEIM(飞鸽传书)的网络协议,详细分析并且实现了FreeEIM(飞鸽传书)的消息传递过程,这里就FreeEIM(飞鸽传书)中的文件和文件夹的传输做详细的说明。   在FreeEIM(飞鸽传书)中,如果要进行文件或者文件夹的传输,首先需要做的就是消息的应答,通过UDP发送文件传输报文,另外的FreeEIM(飞鸽传书)客户端收到报文后,使用TCP协议发送应答报文,这样就开始进行文件的传输了。   这里开启两个线程,线程1负责文件的传送,线程2负责文件的接受,下边做一一说明。   首先,我们知道,可以发送多个文件,这些文件需要建立链表保存信息。   typedef struct file_info   {   struct file_info *next; //双向链表   struct file_info *forward;   char *file; //文件名   int type; //文件类型:文件或者文件夹   int size; //文件大小   struct sockaddr_in addr; //目标网络信息   } FILE_INFO;   [1]文件传送链表由专门的线程维护,这样,线程1就可以专心进行处理文件传输队列就可以了,线程1始终查询这个链表,如果表头为NULL,就说明没有要传输的文件,表头非空,就开始发送报文,获得正确的应答后,就可以开始文件的传输了,文件传输结束,将相应的链表节点删除。这里借鉴了很多程序中使用非常广泛的“命名池”相关的概念,只不过这里我们使用的是“文件池”,可以这么认为,如果有文件要传输,可以不用考虑是否有文件正在传输,只要把要传输的文件放入 “文件池”就可以了 , 同时,不用考虑“文件池”的大小,线程1是文件池的服务线程,它检测文件池的大小,如果非空,就会逐次传输文件。   这里需要特别注意的就是关于文件夹的传输,这个FreeEIM(飞鸽传书)一个难点,应为对与文件夹的内容是没有显示的,需要我们逐次的判断,在飞鸽传书中是这么处理的,如果是一个文件夹,就发送文件属性为IPMSG_FILE_DIR的信息包,FreeEIM(飞鸽传书)客户端收到这个信息包后,就创建这个文件夹,然后发起发送的FreeEIM(飞鸽传书)客户端,进入文件夹,传送文件夹内的文件,如果该文件夹下,还有文件夹,使用相同的方法,在文件夹内的文件传送结束后,就发送FREEEIM_FILE_RETPARENT信息包,接受的FREEEI_FILE_RETP报文的FreeEIM(飞鸽传书)客户端,执行返回上一级目录,FreeEIM(飞鸽传书)发送端,就需发送目录下的文件。这样循环操作,最终完成文件的传输,这个过程比较难以理解。   有了上边的知识,开发文件传输功能就变得简单多了,文件的接受也可以类推了,同样开启一个线程维护接受文件链表,逐次接受身下的文件,链表为空时。文件传输会遇到文件读写问题,有的文件发送是被打开了,这样会造成访问违规,所以要有相应的处理,才能让程序更加稳健。   程序启动时先读取用户配置文件,一般是"*.ini"格式,然后,使用Winsock的广播消息给整个局域网发送一个数据包,这时候,如果其他电脑已经运行了飞鸽传书,那么他收到这个包后,会将包的信息读取出来,当然,这个包里有用户的IP,用户名,性别等等。这样,在用户列表里就多了一个用户了。他的用户检查方式就如此简单而已。至于跨网段的实现,只需简单地修改一下广播地址就行了,如果不考虑速度,你可以给整个internet发广播消息。 消息发送,文件传输这些功能,都比较简单,如果你会网络编程,给你对方IP地址,这些功能实现起来再简单不过了。语音、视屏等,只需编写一些语音视频采集代码,传书的话,就像传文件一样。这里给段广播消息的实现代码吧:   // 发送广播登陆消息   void EM_UserLogin::SendLogin_BC(LPEM_DATA msg)   {   SOCKET m_socket;   m_socket = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);   if (INVALID_SOCKET == m_socket)   {   MessageBox(0, "socket failed.", NULL, MB_OK);   }   SOCKADDR_IN sin;sin.sin_addr.s_addr = htonl(INADDR_BROADCAST);   sin.sin_family = AF_INET;   sin.sin_port = htons(BROADCAST_SEND_PORT);BOOL bOpt = TRUE;   if (SOCKET_ERROR == setsockopt(m_socket, SOL_SOCKET, SO_BROADCAST, (char*)&bOpt, sizeof(bOpt)))   {   // Error occurred   ::MessageBox(0,"BC setsockopt error.",0,0);   return;   }   char *tmpBuf = msg->GetBuffer();   if (SOCKET_ERROR == sendto(m_socket, tmpBuf, msg->GetLength(), 0, (PSOCKADDR)&sin, sizeof(sin)))   {   // Error occurred   ::MessageBox(0,"BC sendto error.",0,0);   return;   }closesocket(m_socket);    相关信息   - 所有的设置信息都保存在注册表的以下位置:   \\HKEY_CURRENT_USER\Software\HSTools\   用户密码以不可逆加密方式存储.   *******************************************************************   * 如果你忘记了密码, 可以在注册表中将此键值删除 *   * \\HKEY_CURRENT_USER\Software\HSTools\IPMsgEng\PasswordStr *   *******************************************************************   - 本软件使用的默认端口为 2425   若仅使用 UDP 协议的端口, 将不能传送文件/文件夹   (如果安装了防火墙, 则必须打开相应的 TCP 和 UDP 端口)   - 本软件为自由软件, 你可以随意传播, 但源码使用请参见许可协议.   - 只有在启动或退出程序, 使用离开模式, 刷新在线用户时 IPMsg 才会进行消息广播.   - 本软件由 Microsoft Visual C++ 6.0 编译 广域网设置(广播设置)   - 主机号全部为 1 的 IP 地址, 即广播地址   例如, 连接到一个 C 类子网(即 24 位网络号, 8 位主机号), IP 地址为   aaa.bbb.ccc.ddd, 其广播地址即为: aaa.bbb.ccc.255   若对方处于另一个私有子网中, 广播可能无效.   - 更多问题, 请参阅相关资料或咨询你的网络管理员.   - 若两台主机的连接经过了多个路由器, 请直接指定对方IP地址   - 拨号上网用户请勾选 [拨号连接]   当刷新在线用户列表时, 列表不会被清空 补充   - 启动飞鸽传书前, 你可以指定其运行时使用的端口,   且可以使用不同的端口打开多个窗口. 用法如下:   ipmsg.exe 2426 (你可在快捷方式上设置)   但是你只能与同时也使用该端口的用户通信.   - 所以你尽可选用你喜欢的端口运行本软件.   介于 10000 至 60000 可能更安全些.   你也可以咨询你的网络管理员.   - 如果有多个网卡(IP), 你可以将飞鸽传书与指定的网卡(IP)进行绑定.   命令格式如下(你可以在快捷方式上设置):   ipmsg.exe [端口] /NIC IP地址   例如:   C:\>ipmsg.exe /NIC 192.168.10.100   - 支持命令方式发送消息   命令格式如下:   ipmsg.exe [端口] /MSG [/LOG][/SEAL] <主机名或IP地址> <消息>   例如:   C:\>ipmsg.exe /MSG /SEAL localhost Hello.    支持   - IPMsg 的技术讨论区是开放的.   如果你想订阅相关邮件, 请联系 ipmsg-subscribe@ring.gr.jp   - 欢迎报告 bug, 以及提出建议   - 如果你有任何疑问, 请 E-mail 联系.   shirouzu@h.email.ne.jp   中文版可联系阿志: hiwyz@163.net   - 发送错误报告, 请勿必记录以下信息:   软件版本, 操作系统, 故障描述, 以及故障重现方法等. 更新历史   ver 1.00 ... 日文版 (1996/08/19)   ver 1.31 ... 英文版/日文版 (1997/09/01)   ver 2.00 ... 英文版/日文版 (2002/11/19)   支持文件/文件夹传送   支持通信数据加密   ver 2.03 ... Bug 修正 (文件传送引起缓冲溢出)   广播设置支持主机地址(FQDN)解析   ver 2.04 ... 增加绑定网卡(IP)功能   ver 2.05 ... Bug 修正 (2.04版当激活发送/接收消息窗口时,无法注销/关闭系统)   ver 2.06 ... 很小的调整   ver 2007 ... 全面调整软件的界面可用性、性能稳定性 注意:本版本为 IPMSG 2.06版 编译环境: WINXP & VS2005, 可正确编译。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值