C++基于socket UDP网络编程实现简单聊天室功能

C++基于Socket UDP网络编程实现简单聊天室功能完整攻略

本文将为大家分享C++基于Socket UDP网络编程实现简单聊天室功能的完整攻略,涵盖环境搭建、UDP协议基础、聊天室实现等方面的内容。

环境搭建

在开始网络编程前,我们需要搭建基础的环境。具体步骤如下:

  1. 安装Visual Studio(根据自己的操作系统安装对应版本),并创建一个空项目。

  2. 在项目目录下创建一个新的cpp文件,命名为“main.cpp”。

  3. 在VS的菜单栏中,依次选择“项目”--“属性”,在属性页面中选择“配置属性”--“VC++目录”--“包含目录”,并添加"WS2_32.lib"库。

现在我们已经成功搭建了C++ Socket网络编程的开发环境。

UDP协议基础

在实现聊天室功能前,我们需要了解UDP协议的基本知识。

UDP是一种无连接的传输协议,其不仅仅对数据包的长度进行控制,同时它也不能保证数据包的可靠传输。UDP在网络应用中通常用于传输那些允许一定量数据丢失的应用数据。

UDP包含了两个重要的概念:数据报和数据包。其中,数据报是指应用程序为传输而准备的消息,而数据包则是指传输的基本单位,包含了发送者和接收者的IP地址和端口号等信息。

下面给出两个示例,以更好的理解和掌握UDP协议:

示例1: UDP服务器与客户端通信

下面来简单介绍一下基于UDP协议的服务端和客户端通信。先看服务端代码:

#include <stdio.h>
#include <winsock2.h><!---Windows下使用socket需要引入的头文件--->
#define BUF_SIZE 30
#pragma comment(lib, "ws2_32.lib")<!---连接WS2_32.lib库--->
int main() {
    WSADATA wsaData;
    SOCKET servSock, clntSock;
    char message[BUF_SIZE];
    int strLen, i;
    SOCKADDR_IN servAddr, clntAddr;
    int clntAddrSize;
    if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
        error_handling("WSAStartup() error!");
    servSock = socket(PF_INET, SOCK_DGRAM, 0);<!---创建服务端套接字--->
    if (servSock == INVALID_SOCKET) error_handling("socket() error");
    memset(&servAddr, 0, sizeof(servAddr));
    servAddr.sin_family = AF_INET;
    servAddr.sin_addr.s_addr = htonl(INADDR_ANY);<!---获取所有地址--->
    servAddr.sin_port = htons(1234);
    if (bind(servSock, (SOCKADDR*)&servAddr, sizeof(servAddr)) == SOCKET_ERROR)  error_handling("bind() error");
    while (1) {
        clntAddrSize = sizeof(clntAddr);
        strLen = recvfrom(servSock, message, BUF_SIZE, 0, (SOCKADDR*)&clntAddr, &clntAddrSize);
        sendto(servSock, message, strLen, 0, (SOCKADDR*)&clntAddr, sizeof(clntAddr));
    }
    closesocket(servSock);
    WSACleanup();
    return 0;
}

再来看客户端代码:

#include <stdio.h>
#include <winsock2.h>
#define BUF_SIZE 30
#pragma comment(lib, "ws2_32.lib")

void error_handling(char* message);

int main(int argc, char** argv) {
    WSADATA wsaData;
    SOCKET sock;
    char message[BUF_SIZE];
    int strLen;
    SOCKADDR_IN servAddr;
    if (argc != 3) {
        printf("Usage: %s <IP> <PORT>\n", argv[0]);
        exit(1);
    }
    if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) error_handling("WSAStartup() error!");
    sock = socket(PF_INET, SOCK_DGRAM, 0);
    if (sock == INVALID_SOCKET) error_handling("socket() error");

    memset(&servAddr, 0, sizeof(servAddr));
    servAddr.sin_family = AF_INET;
    servAddr.sin_addr.s_addr = inet_addr(argv[1]);
    servAddr.sin_port = htons(atoi(argv[2]));

    while (1) {
        fputs("Insert message(q to quit): ", stdout);
        fgets(message, sizeof(message), stdin);
        if (!strcmp(message, "q\n")) break;
        sendto(sock, message, strlen(message), 0,
            (SOCKADDR*)&servAddr, sizeof(servAddr));
        strLen = recvfrom(sock, message, BUF_SIZE, 0, NULL, 0);
        message[strLen] = 0;
        printf("Message from server: %s", message);
    }
    closesocket(sock);
    WSACleanup();
    return 0;
}

void error_handling(char* message) {
    fputs(message, stderr);
    fputc('\n', stderr);
    exit(1);
}

客户端和服务端都是采用了套接字,套接字是应用程序使用的实现网络协议的一种方式。程序通过用两个套接字(socket)来创建一条网络连接并进行通信。

示例2: UDP实现广播

广播是指将一条信息从一台主机发送到同一局域网中的所有主机上,下面来看通过UDP实现广播的基本方法。

广播通过指定一个网段来确定广播范围,在Windows中常使用255.255.255.255表示广播。下面是一个简单的UDP广播示例:

#include <winsock2.h>
#include <windows.h>
#include <stdio.h>
void ErrorHandling(char *message);
#pragma comment(lib, "ws2_32.lib")
#define TTL 64
#define BUF_SIZE 30

int main() {
    WSADATA wsaData;
    SOCKET sock;
    int timeLive = TTL;
    char MSG[BUF_SIZE];
    SOCKADDR_IN sendAddr;
    HANDLE hThread;
    DWORD dwThreadID;

    if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
        ErrorHandling("WSAStartup() error!");

    sock = socket(PF_INET, SOCK_DGRAM, 0);
    if (sock == INVALID_SOCKET)
        ErrorHandling("socket() error");

    memset(&sendAddr, 0, sizeof(sendAddr));
    sendAddr.sin_family = AF_INET;
    sendAddr.sin_addr.s_addr = inet_addr("255.255.255.255");
    sendAddr.sin_port = htons(9999);

    setsockopt(sock, IPPROTO_IP, IP_MULTICAST_TTL, (void*)&timeLive, sizeof(timeLive));

    hThread = CreateThread(NULL, 0, sendMsg, (LPVOID)sock, 0, &dwThreadID);
    if (hThread == NULL) ErrorHandling("CreateThread() error!");

    printf("press any key to quit~\n");
    getchar();
    closesocket(sock);
    WSACleanup();
}

DWORD WINAPI sendMsg(LPVOID lpParam) {
    char MSG[BUF_SIZE] = "Hello";
    SOCKADDR_IN sendAddr;
    SOCKET sock = (SOCKET)lpParam;
    while (true) {
        Sleep(1000);
        sendto(sock, MSG, strlen(MSG), 0, (SOCKADDR*)&sendAddr, sizeof(sendAddr));
    }
    return 0;
}

void ErrorHandling(char *message) {
    fputs(message, stderr);
    fputc('\n', stderr);
    exit(1);
}

在以上代码中,我们使用了Setsockopt()方法来设置网络的一些参数,其中IP_MULTICAST_TTL是广播域中的时间跨度,即发送消息的路由所能到达的最大跳数。

聊天室实现

在UDP协议和套接字方面的知识铺垫下,我们可以开始实现简单的聊天室。

为了实现这一目标,我们需要有以下几个步骤:

  1. 启动服务端:由一个用户来创建一个服务端程序,建立一个套接字并绑定在一个IP地址和一个端口号上等待客户端的连接请求。

  2. 启动客户端:用户启动客户端程序,通过套接字连接到服务端并发送命令。

  3. 客户端发送消息:客户端向服务端发送消息,服务端接收判断消息类型并作出相应的处理,如果是群发或单独发送给指定对象,则将消息发送给所有在线客户端或指定对象的客户端。

  4. 客户端接受消息:客户端接收其他客户端消息并显示在自己的聊天框中。

下面是一个简单的聊天室实现代码示例:

#include <stdio.h>
#include <winsock2.h>
#pragma comment(lib, "ws2_32.lib")

#define BUF_SIZE 100
void error_handle(const char* message);
void send_msg(FILE* fp, SOCKET sock);

int main(int argc, char* argv[]) {
    if (argc != 4) {
        printf("Usage : %s <ip> <port> <name>\n", argv[0]);
        exit(1);
    }

    int port = atoi(argv[2]);
    char name[BUF_SIZE];
    sprintf(name, "[%s]", argv[3]);

    SOCKET sock;
    SOCKADDR_IN serv_addr;

    FILE* fp;
    if (fopen_s(&fp, "chatlog.txt", "at") != 0) error_handle("file opening error");

    if (WSAStartup(MAKEWORD(2, 2), (WSADATA*)&serv_addr) != 0) error_handle("WSAStartup error");

    sock = socket(PF_INET, SOCK_DGRAM, 0);
    if (sock == INVALID_SOCKET) error_handle("Socket() error");

    memset(&serv_addr, 0, sizeof(serv_addr));
    serv_addr.sin_family = AF_INET;
    serv_addr.sin_addr.s_addr = inet_addr(argv[1]);
    serv_addr.sin_port = htons(port);

    if (connect(sock, (SOCKADDR*)&serv_addr, sizeof(serv_addr)) == SOCKET_ERROR) error_handle("connect() error");

    send_msg(fp, sock);
    closesocket(sock);
    fclose(fp);
    return 0;
}

void send_msg(FILE* fp, SOCKET sock) {
    char msg[BUF_SIZE + 1];
    while (1) {
        if (fgets(msg, BUF_SIZE, stdin) == NULL) break;
        if (!strcmp(msg, "q\n") || !strcmp(msg, "Q\n")) break;

        send(sock, msg, strlen(msg), 0);
    }
}

void error_handle(const char* message) {
    printf("%s\n", message);
    exit(1);
}

在以上代码中,我们使用了Socket套接字来实现网络编程,并使用了Send()方法将信息发送至服务端。

至此,你已经拥有使用C++基于Socket UDP网络编程实现简单聊天室功能的完整攻略,希望对于你的学习和实践有所帮助。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:C++基于socket UDP网络编程实现简单聊天室功能 - Python技术站

(0)
上一篇 2023年6月26日
下一篇 2023年6月26日

相关文章

  • Element-ui upload上传文件限制的解决方法

    当使用 Element-ui 的 Upload 组件时,我们可能会遇到一些文件大小或文件数量的限制问题。这里提供一些解决这类问题的方法。 限制上传文件数量 我们可以使用 Element-ui 的 limit 属性来限制可以上传的文件数量。例如,以下代码将限制用户最多只能上传 3 个文件: <el-upload :limit="3" …

    other 2023年6月27日
    00
  • android 关于利用签名的SHA1进行安全校验的方法之一(推荐)

    以下是利用签名的SHA1进行安全校验的方法之一的完整攻略: Android应用签名和SHA1获取 生成签名文件:使用Android Studio生成应用的签名文件(.jks或.keystore文件)。可以通过以下步骤生成签名文件: 打开Android Studio,选择“Build”菜单,然后选择“Generate Signed Bundle/APK”。 选…

    other 2023年10月14日
    00
  • 详解vue中使用protobuf踩坑记

    详解Vue中使用Protobuf踩坑记 1. 什么是Protobuf Protobuf全称为Protocol Buffers,是一种由Google开发的数据序列化协议。 Protobuf支持不同语言之间的数据传输,可以在不同的系统之间高效地传递数据。 Protobuf定义的数据结构,可以通过.proto文件来描述。使用特定工具库可以方便地在不同编程语言中使用…

    other 2023年6月26日
    00
  • Android 自定义星评空间示例代码

    Android 自定义星评空间示例代码攻略 本文将详细讲解自定义星评空间示例代码的实现过程。星评空间可以用于用户评分等场景,采用自定义控件实现,较为灵活。具体步骤如下: 1.设计界面和布局 首先,需要在Android Studio中新建一个布局文件,设计星级评分控件的UI界面。依据需求,可以添加TextView、ImageView等视图。其中,TextVie…

    other 2023年6月25日
    00
  • iPhone6 Plus无限重启怎么办 iPhone6老是自动重启解决办法

    iPhone6 Plus无限重启的解决办法 问题描述 iPhone6 Plus突然出现无限重启的问题。 可能原因 软件问题 系统损坏 硬件故障 解决办法 方法一:硬重置 按住电源键和Home键,直到出现苹果标志。 松开按键,等待设备启动。 如果无限重启的问题仍然存在,请尝试方法二。 方法二:进入安全模式 按住电源键直至出现 Slide to power of…

    other 2023年6月27日
    00
  • Flutter 中如何优雅的实现多渠道打包(埋点统计系列)

    Flutter 中如何优雅的实现多渠道打包(埋点统计系列) 本文将为您详细讲解如何在Flutter中优雅地实现多渠道打包,包括环境搭建、配置文件修改、打包命令和示例说明等步骤。 环境搭建 在开始实现多渠道打包之前,需要先在Flutter项目中添加flutter_channel插件。可以按照以下步骤进行操作: 在pubspec.yaml文件中添加flutter…

    other 2023年5月6日
    00
  • 电脑提示关键错误的解决方法

    电脑提示关键错误的解决方法 当我们使用电脑的过程中,经常会遇到电脑提示关键错误的情况,这时我们就需要采取一些解决措施来修复这个问题,以下是具体步骤: 步骤一:查看错误提示信息 当电脑提示关键错误时,我们需要查看错误提示信息,以便更好地了解问题产生的原因。这里有两个示例: 如果你的电脑提示“操作系统未找到”,这可能是由于硬盘出现故障或系统文件损坏导致的。此时,…

    other 2023年6月27日
    00
  • Win11系统TCP协议怎么修改ip地址? Win11 Internet协议的设置方法

    Win11系统TCP协议修改IP地址攻略 1. 打开网络和Internet设置 首先,我们需要打开Win11的网络和Internet设置界面。可以通过以下步骤进行操作: 点击任务栏右下角的网络图标(Wi-Fi或以太网连接图标)。 在弹出的网络菜单中,点击\”网络和Internet设置\”。 2. 进入网络设置 在网络和Internet设置界面,我们需要进入网…

    other 2023年7月30日
    00
合作推广
合作推广
分享本页
返回顶部