C++基于Socket UDP网络编程实现简单聊天室功能完整攻略
本文将为大家分享C++基于Socket UDP网络编程实现简单聊天室功能的完整攻略,涵盖环境搭建、UDP协议基础、聊天室实现等方面的内容。
环境搭建
在开始网络编程前,我们需要搭建基础的环境。具体步骤如下:
-
安装Visual Studio(根据自己的操作系统安装对应版本),并创建一个空项目。
-
在项目目录下创建一个新的cpp文件,命名为“main.cpp”。
-
在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协议和套接字方面的知识铺垫下,我们可以开始实现简单的聊天室。
为了实现这一目标,我们需要有以下几个步骤:
-
启动服务端:由一个用户来创建一个服务端程序,建立一个套接字并绑定在一个IP地址和一个端口号上等待客户端的连接请求。
-
启动客户端:用户启动客户端程序,通过套接字连接到服务端并发送命令。
-
客户端发送消息:客户端向服务端发送消息,服务端接收判断消息类型并作出相应的处理,如果是群发或单独发送给指定对象,则将消息发送给所有在线客户端或指定对象的客户端。
-
客户端接受消息:客户端接收其他客户端消息并显示在自己的聊天框中。
下面是一个简单的聊天室实现代码示例:
#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技术站