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

yizhihongxing

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日

相关文章

  • Android应用的LinearLayout中嵌套RelativeLayout的布局用法

    当在Android应用中使用LinearLayout嵌套RelativeLayout时,可以实现更复杂的布局结构和更灵活的UI设计。下面是详细的攻略: 首先,在XML布局文件中创建一个LinearLayout,并设置其方向(垂直或水平)和其他属性。例如: <LinearLayout xmlns:android=\"http://schemas…

    other 2023年7月28日
    00
  • android网络编程系列一javasecurity之jsse(ssl/tls)

    以下是“Android网络编程系列一Java Security之JSSE(SSL/TLS)”的完整攻略,包括两个示例说明。 Android网络编程系列一Java Security之JSSE(SSL/TLS) 在网络编程中,JSSE(Java Secure Socket Extension)是一种常用的安全套接字扩展,用于提供SSL/TLS协议的支持。以下是一…

    other 2023年5月10日
    00
  • 详细谈谈C语言中动态内存

    详细讲解C语言中动态内存的完整攻略 动态内存是C语言中一种重要的内存管理技术,它允许程序在运行时动态地分配和释放内存。在C语言中,动态内存的管理是通过使用malloc、calloc、realloc和free等函数来实现的。下面将详细介绍这些函数的使用方法,并提供两个示例说明。 1. malloc函数 malloc函数用于在堆上分配指定大小的内存块,并返回指向…

    other 2023年8月1日
    00
  • MySQL命令行删除表中的一个字段

    MySQL命令行删除表中的一个字段的完整攻略分为以下几个步骤: 步骤一:进入MySQL命令行 首先需要通过以下命令进入MySQL命令行: mysql -u username -p 其中,username为你的MySQL用户名。输入以上命令后会提示你输入密码,输入密码后回车即可进入MySQL命令行。 步骤二:选择数据库 进入MySQL命令行后,需要选择要操作的…

    other 2023年6月25日
    00
  • Android BroadcastReceiver广播注册方式总结

    Android BroadcastReceiver广播注册方式总结 概述 在Android系统中,广播是一种非常常用的通信方式,用于在不同组件之间传递信息。BroadcastReceiver是Android中的四大组件之一,用于接收和处理广播信息。为了让BroadcastReceiver能够接收到广播,我们需要将其注册到系统中。 BroadcastRecei…

    other 2023年6月27日
    00
  • 在Linux 命令行终端分屏的两种工具

    在Linux命令行终端中,有时候需要同时运行多个命令或程序,为了方便查看和管理,可以使用终端分屏工具。下面将介绍两种常用的终端分屏工具: 1. tmux tmux是一款强大的终端复用工具,可以同时在一个终端窗口中运行多个终端会话,并能够在它们之间切换和管理。以下是使用tmux的基本流程: 1.1 安装和启动tmux 在终端中输入以下命令安装tmux: sud…

    other 2023年6月26日
    00
  • 使用Python将Mysql的查询数据导出到文件的方法

    将Mysql的查询数据导出到文件,可以采用Python的MySQLdb库来实现。具体步骤如下: 安装MySQLdb库 可以通过pip命令来安装: pip install MySQLdb 连接MySQL数据库 使用MySQLdb库的connect函数连接MySQL数据库,需要提供MySQL数据库的地址、端口、用户名、密码以及数据库名称等参数,示例代码如下: i…

    other 2023年6月26日
    00
  • 详解浏览器渲染页面过程

    详解浏览器渲染页面过程的完整攻略 1. 解析HTML 当浏览器接收到HTML文档时,它会开始解析该文档。解析过程包括以下几个步骤: 词法分析:将HTML文档分解为一系列的标记(tokens),如标签、属性和文本内容。 语法分析:根据HTML规范,将标记组织成一个树状结构,即DOM树(Document Object Model)。 2. 构建DOM树 DOM树…

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