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日

相关文章

  • 使用instsrv.exe+srvany.exe将应用程序安装为windows服务的方法

    将应用程序安装为 Windows 服务是使应用程序在系统启动时自动运行的常见方法。以下是使用 instsrv.exe 和 srvany.exe 工具将应用程序安装为 Windows 服务的步骤: 准备工作 在开始之前,需先下载 Windows Server 2003 Resource Kit Tools,其中包含了 instsrv.exe 和 srvany.…

    other 2023年6月25日
    00
  • java中int怎样转换成string?

    在Java中将int类型转换为String类型有两种方法:使用String类的静态方法valueOf()和使用Integer类的toString()方法。我们来详细了解一下这两种方法。 方法一:使用String类的valueOf()方法 使用String类的valueOf()方法可以将int类型的数据转换为String类型的数据。 int num = 123…

    其他 2023年4月16日
    00
  • 详解WPF中用户控件和自定义控件的使用

    详解WPF中用户控件和自定义控件的使用 WPF中的控件可以根据我们的需要进行自定义,这就涉及到两种方式:用户控件和自定义控件。本文将详细讲解这两种方式的使用方法。 用户控件 用户控件是由多个控件组成的可重用控件。我们可以将多种原生控件组合在一起,用 C# 或 VB.NET 编写代码,从而构建出一个新的用户控件。在开发过程中,用户控件可以像其他控件那样使用、放…

    other 2023年6月25日
    00
  • Golang执行cmd命令行的方法

    下面是关于Golang执行cmd命令行的方法的完整攻略: 1. 使用os包 通过os包可以在Golang中执行cmd命令行。 package main import ( "fmt" "os/exec" ) func main() { // 创建cmd命令行的执行对象 cmd := exec.Command("…

    other 2023年6月27日
    00
  • windows电脑使用简单命令 实现个性化弹窗的技巧

    下面是讲解“Windows电脑使用简单命令实现个性化弹窗的技巧”的完整攻略。 1. 准备工作 在开始编写命令之前,需要先确定弹窗需要展示什么内容。可以使用文本编辑器或记事本编写弹窗内容,然后将其保存为 .txt 格式的文件。在本例中,我们以 “Hello World” 作为示例弹窗文本。 2. 使用命令创建弹窗 在 Windows 操作系统中,可以使用 ms…

    other 2023年6月26日
    00
  • @ConfigurationProperties绑定配置信息至Array、List、Map、Bean的实现

    @ConfigurationProperties 是 Spring Boot 中的一个注解,它允许我们将应用程序中的配置文件绑定到 Bean 上。绑定后,我们就可以方便地将配置文件的配置值注入到 Bean 中了。除了一个普通的扩展 @ConfigurationProperties 的 Spring Boot Config 类之外,我们还可以将属性绑定到 Co…

    other 2023年6月25日
    00
  • 关于css:如何更改bootstrap的全局默认字体大小

    关于CSS:如何更改Bootstrap的全局默认字体大小 Bootstrap是一个流行的前端框架,它提供了许多预定义的样式和组件,可以帮助我们快速构建漂亮的网站。在使用Bootstrap时有时需要更改全局默认字体大小,本攻略将详细介绍如何实现这一目标,并提供两个示例说明。 解决方法 要更改Bootstrap的全局默认字体大小,可以使用以下两种方法: 方法一:…

    other 2023年5月7日
    00
  • 苹果iOS9.3.3正式版官方固件下载地址汇总

    苹果iOS9.3.3正式版官方固件下载地址汇总攻略 苹果iOS9.3.3正式版官方固件是一款用于iPhone、iPad和iPod Touch设备的操作系统。本攻略将详细介绍如何获取iOS9.3.3正式版官方固件的下载地址。 步骤一:访问苹果官方网站 首先,打开您的浏览器,并访问苹果官方网站(https://www.apple.com)。 步骤二:导航至支持页…

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