C/C++ 开发一款多人聊天室

基于UDP协议实现

服务端代码:

// Test_Console.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include <iostream>
#include <WinSock2.h>
#include <WS2tcpip.h>
#include <Windows.h>
#include <thread>
#include <cstdio>

using namespace std;

#pragma region 全局变量

SOCKET server;					// 服务端套接字
sockaddr_in sai_server;			// 服务端信息(ip、端口)

// 消息格式
struct umsg {
	int type;				// 协议(1:加入 2:退出 3:发消息)
	char name[64];			// 用户名字
	char text[512];			// 文本信息
};

// 客户端链表
typedef struct ucnode {
	sockaddr_in addr;		// 客户端的地址和端口号
	umsg msg;				// 客户端传来的消息
	ucnode* next;
} *ucnode_t;

#pragma endregion


#pragma region 依赖函数

// 链表插入数据
ucnode* insertNode(ucnode* head, sockaddr_in addr,umsg msg) {
	ucnode* newNode = new ucnode();
	newNode->addr = addr;
	newNode->msg = msg;
	ucnode* p = head;
	if (p == nullptr) {
		head = newNode;
	}
	else {
		while (p->next != nullptr) {
			p = p->next;
		}
		p->next = newNode;
	}
	return head;
}

// 链表删除数据
ucnode* deleteNode(ucnode* head, umsg msg) {
	ucnode* p = head;
	if (p == nullptr) {
		return head;
	}
	if (strcmp(p->msg.name, msg.name) == 0){
		head = p->next;
		delete p;
		return head;
	}
	while (p->next != nullptr && strcmp(p->next->msg.name, msg.name) != 0) {
		p = p->next;
	}
	if (p->next == nullptr) {
		return head;
	}
	ucnode* deleteNode = p->next;
	p->next = deleteNode->next;
	delete deleteNode;
	return head;
}

#pragma endregion

int main()
{
	cout << "我是服务端" << endl;

	// 初始化 WSA ,激活 socket
	WSADATA wsaData;
	if (WSAStartup(
		MAKEWORD(2, 2), 		// 规定 socket 版本为 2.2
		&wsaData				// 接收关于套接字的更多信息
		)) {
		cout << "WSAStartup failed : " << GetLastError() << endl;
	}

	// 初始化 socket、服务器信息
	server = socket(
		AF_INET, 		// IPV4
		SOCK_DGRAM,		// UDP
		0				// 不指定协议
		);
	sai_server.sin_addr.S_un.S_addr = 0;	// IP地址
	sai_server.sin_family = AF_INET;		// IPV4
	sai_server.sin_port = htons(8090);		// 传输协议端口

	// 本地地址关联套接字
	if (bind(
		server, 					// 要与本地地址绑定的套接字
		(sockaddr*)&sai_server, 	// 用来接收客户端消息的 sockaddr_in 结构体指针
		sizeof(sai_server)			
		)) {
		cout << "bind failed : " << GetLastError() << endl;
		WSACleanup();
	}

	// 初始化客户端链表
	ucnode* listHead = new ucnode();
	listHead->next = nullptr;
	ucnode* lp = listHead;

	// 监听消息
	while (1) {
		// 接收来自客户端的消息
		umsg msg;
		int len_client = sizeof(sockaddr);
		recvfrom(
			server, 					// 本地套接字
			(char*)&msg, 				// 存放接收到的消息
			sizeof(msg), 				
			0, 							// 不修改函数调用行为
			(sockaddr*)&sai_server, 	// 接收客户端的IP、端口
			&len_client					// 接收消息的长度,必须初始化,否则默认为0 收不到消息				
		);
		
		// sin_addr 转 char[](char[] 转 sin_addr 使用 inet_top)
		char arr_ip[20];
		inet_ntop(AF_INET, &sai_server.sin_addr, arr_ip, 16);
		
		// 处理消息(1:用户登录,2:用户退出,3:普通会话)
		switch (msg.type) {
		case 1: 
			insertNode(listHead, sai_server, msg); 
			cout << "[" << arr_ip << ":" << ntohs(sai_server.sin_port) << "] " << msg.name << ":" << "---登录---" << endl;
			break;
		case 2:
			deleteNode(listHead, msg);
			cout << "[" << arr_ip << ":" << ntohs(sai_server.sin_port) << "] " << msg.name << ":" << "---退出---" << endl;
			break;
		case 3:
			cout << "[" << arr_ip << ":" << ntohs(sai_server.sin_port) << "] " << msg.name << ":" << msg.text << endl;
			// 更新 msg.text
			lp = listHead;
			while (lp) {
				if (strcmp(lp->msg.name, msg.name) == 0) {
					strncpy(lp->msg.text, msg.text, sizeof(msg.text));
					lp->msg.type = msg.type;
					break;
				}
				lp = lp->next;
			}
			// 向其他客户端广播(除自己之外)
			lp = listHead;
			while (lp) {
				if (strcmp(lp->msg.name,"") != 0 && strcmp(lp->msg.name, msg.name) != 0) {
					sendto(
						server, 					// 本地套接字
						(char*)&msg, 				// 消息结构体
						sizeof(msg), 				
						0, 							// 不修改函数调用行为
						(sockaddr*) & lp->addr, 	// 目标客户端地址
						sizeof(lp->addr)
					);
				}
				lp = lp->next;
			}
			break;
		}
	}

	// 禁用 socket
	WSACleanup();

	getchar();
    return 0;
}

客户端代码:

#include <iostream>
#include <WinSock2.h>
#include <WS2tcpip.h>
#include <Windows.h>
#include <thread>
#include <cstdio>
#include <string>

#pragma comment(lib,"ws2_32.lib")

using namespace std;

#pragma region 全局变量

SOCKET client;					// 客户端套接字		
sockaddr_in sai_client;			// 存放客户端地址、端口
sockaddr_in sai_server;			// 存放服务端发送的消息

// 发送和接收的信息体
struct umsg {
	int type;					// 协议(1:登录,2:退出,3:发消息)
	char name[64];				// 用户名字
	char text[512];				// 文本
};

#pragma endregion

#pragma region 依赖函数

// 监听服务器消息
void recvMessage()
{
	while (1){
		umsg msg;
		int len_server = sizeof(sockaddr);
		int len = recvfrom(client, (char*)&msg,sizeof(msg),0,(sockaddr*)&sai_server,&len_server);
		
		cout << msg.name << ": " << msg.text << endl;
	}
}

#pragma endregion

int main()
{
	cout << "我是客户端" << endl;

	// 初始化 WSA ,激活 socket
	WSADATA wsaData;
	if (WSAStartup(
		MAKEWORD(2, 2), 	// 规定 socket 版本
		&wsaData			// 接收 socket 的更多信息
		)) {
		cout << "WSAStartup failed : " << GetLastError() << endl;
	}

	// 初始化 socket、客户端信息
	client = socket(
		AF_INET,		// IPV4
		SOCK_DGRAM,		// UDP
		0				// 不指定协议
		);
	sai_client.sin_family = AF_INET;									// IPV4
	inet_pton(AF_INET, "192.168.1.105", &sai_client.sin_addr);			// 服务器 IP地址
	sai_client.sin_port = htons(8090);									// 端口

	// 输入用户名
	string name;
	getline(cin, name);

	// 发送登录消息
	umsg msg;
	msg.type = 1;
	strncpy_s(msg.name, sizeof(msg.name), name.c_str(), 64);
	strncpy_s(msg.text, sizeof(msg.text), "", 512);
	sendto(
		client, 						// 本地套接字
		(char*)&msg, 					// 发送的消息
		sizeof(msg), 
		0, 								// 不修改函数调用行为
		(sockaddr*) & sai_client,		// 消息目标
		sizeof(sai_client)
	);

	// 接收服务器消息
	HANDLE h_recvMes = CreateThread(0, 0, (LPTHREAD_START_ROUTINE)recvMessage, 0, 0, 0);
	if (!h_recvMes) { cout << "CreateThread failed :" << GetLastError() << endl; }
    
	// 发送消息
	while (1) {
		string content;
		getline(cin, content);
		
		// 如果是退出消息
		if (content == "quit") {
			msg.type = 2;
			sendto(client, (char*)&msg, sizeof msg, 0, (struct sockaddr*) & sai_client, sizeof(sai_client));
			closesocket(client);
			WSACleanup();
			return 0;
		}

		// 如果是会话消息
		msg.type = 3;
		strncpy_s(msg.text, sizeof(msg.text), content.c_str(), 512);
		sendto(
			client, 						// 本地套接字
			(char*)&msg, 					// 要发送的消息
			sizeof(msg), 
			0, 								// 不修改函数调用行为
			(sockaddr*) & sai_client, 		// 发送目标
			sizeof(sai_client)
		);
	}


    getchar();
    return 0;
}

基于TCP实现

服务端代码

#include "stdafx.h"
#include <iostream>
#include <WinSock2.h>
#include <WS2tcpip.h>
#include <Windows.h>
#include <thread>
#include <cstdio>

using namespace std;

#pragma region 全局变量

SOCKET server;				// 本地套接字
sockaddr_in sai_server;		// 存放服务器IP、端口

// 消息格式
struct umsg {
	int type;				// 协议(1:登录,2:退出,3:发消息)
	char name[64];			// 用户名字
	char text[512];			// 文本信息
};

// 客户端信息
struct clientInfo {
	SOCKET client;
	sockaddr_in saddr;
	umsg msg;
};

// 客户端链表
typedef struct ucnode {
	clientInfo cInfo;
	ucnode* next;
} *ucnode_t;

ucnode* listHead;		// 客户端链表头
ucnode* lp;				// 客户端链表指针

#pragma endregion

#pragma region 依赖函数

// 链表插入数据
ucnode* insertNode(ucnode* head,SOCKET client, sockaddr_in addr, umsg msg) {
	ucnode* newNode = new ucnode();
	newNode->cInfo.client = client;
	newNode->cInfo.saddr = addr; 
	newNode->cInfo.msg = msg;
	ucnode* p = head;
	if (p == nullptr) {
		head = newNode;
	}
	else {
		while (p->next != nullptr) {
			p = p->next;
		}
		p->next = newNode;
	}
	return head;
}

// 链表删除数据
ucnode* deleteNode(ucnode* head, SOCKET client) {
	ucnode* p = head;
	if (p == nullptr) {
		return head;
	}
	if (p->cInfo.client == client) {
		head = p->next;
		delete p;
		return head;
	}
	while (p->next != nullptr && p->next->cInfo.client != client) {
		p = p->next;
	}
	if (p->next == nullptr) {
		return head;
	}
	ucnode* deleteNode = p->next;
	p->next = deleteNode->next;
	delete deleteNode;
	return head;
}

// 接收客户端消息(某个)
void recvMessage(PVOID pParam) {
	clientInfo* cInfo = (clientInfo*)pParam;

	while (1) {
		// 接收来自客户端的消息
		umsg msg;
		int len_client = sizeof(sockaddr);
		int ret_recv = recv(
			cInfo->client,	// 本地套接字	
			(char*)&msg,	// 存放接收的消息
			sizeof(msg),	// 消息大小
			0				// 不修改函数调用行为
		); 
		if (ret_recv <= 0) { cout << msg.name << "断开连接: " << GetLastError() << endl; break; }
		cInfo->msg = msg;

		// sin_addr 转 char[](char[] 转 sin_addr 使用 inet_top)
		char arr_ip[20];
		inet_ntop(AF_INET, &cInfo->saddr.sin_addr, arr_ip, 16);

		// 处理消息(1:登录,2:退出,3:会话)
		switch (cInfo->msg.type) {
		case 1:
			// 插入数据到链表
			insertNode(listHead,cInfo->client, cInfo->saddr,cInfo->msg);
			// 打印消息
			cout << "[" << arr_ip << ":" << ntohs(cInfo->saddr.sin_port) << "] " << msg.name << ":" << "---登录---" << endl;
			break;
		case 2:
			// 从链表删除数据
			deleteNode(listHead, /*cInfo->msg*/cInfo->client);
			// 打印消息
			cout << "[" << arr_ip << ":" << ntohs(cInfo->saddr.sin_port) << "] " << msg.name << ":" << "---退出---" << endl;
			break;
		case 3:
			// 打印消息
			cout << "[" << arr_ip << ":" << ntohs(cInfo->saddr.sin_port) << "] " << msg.name << ":" << cInfo->msg.text << endl;
			// 向其他客户端广播(除自己之外)
			lp = listHead;
			while (lp) {
				if (strcmp(lp->cInfo.msg.name, "") != 0 && strcmp(lp->cInfo.msg.name, cInfo->msg.name) != 0) {
					send(
						lp->cInfo.client,		// 本地套接字
						(char*)&cInfo->msg,		// 发送的消息
						sizeof(cInfo->msg),		// 消息大小
						0						// 不指定调用方式
					);
					int error_send = GetLastError();
					if (error_send != 0) { cout << "send failed:" << error_send << endl; }
				}
				lp = lp->next;
			}
			break;
		}
	}
}

#pragma endregion

int main()
{
	cout << "我是服务端" << endl;

	// 初始化 WSA ,激活 socket
	WSADATA wsaData;
	if (WSAStartup(
		MAKEWORD(2, 2), 		// 规定 socket 版本为 2.2
		&wsaData				// 接收关于套接字的更多信息
	)) {
		cout << "WSAStartup failed : " << GetLastError() << endl;
	}

	// 初始化 socket、服务器信息
	server = socket(
		AF_INET, 		// IPV4
		SOCK_STREAM,	// TCP
		0				// 不指定协议
	);
	sai_server.sin_addr.S_un.S_addr = 0;	// IP地址
	sai_server.sin_family = AF_INET;		// IPV4
	sai_server.sin_port = htons(8090);		// 传输协议端口

	// 本地地址关联套接字
	if (bind(
		server, 					// 要与本地地址绑定的套接字
		(sockaddr*)&sai_server, 	// 用来接收客户端消息的 sockaddr_in 结构体指针
		sizeof(sai_server)
	)) {
		cout << "bind failed : " << GetLastError() << endl;
		WSACleanup();
	}

	// 套接字进入监听状态
	listen(
		server,		// 本地套接字
		SOMAXCONN	// 挂起连接队列的最大长度,SOMAXCONN:最大合理值
	);

	// 初始化客户端链表
	listHead = new ucnode();
	listHead->next = nullptr;
	lp = listHead;
		
	// 接收消息
	while (1) {
		// 接收登录消息(首次连接是触发,之后发送消息不触发)
		clientInfo* cInfo = new clientInfo();
		int len_client = sizeof(sockaddr);
		cInfo->client = accept(server, (sockaddr*) &cInfo->saddr, &len_client);	
		if (GetLastError() != 0) { continue; }
		
		// 接收登录者的消息(每个客户端对应一个线程)
		HANDLE h_recvMes = CreateThread(0, 0, (LPTHREAD_START_ROUTINE)recvMessage, cInfo, 0, 0);
		if (!h_recvMes) { cout << "CreateThread failed :" << GetLastError() << endl; }
	}

	// 禁用 socket
	WSACleanup();

	getchar();
    return 0;
}

客户端代码:

#include <iostream>
#include <WinSock2.h>
#include <WS2tcpip.h>
#include <Windows.h>
#include <thread>
#include <cstdio>
#include <string>

#pragma comment(lib,"ws2_32.lib")

using namespace std;

#pragma region 全局变量

SOCKET client;					// 本地套接字
sockaddr_in sai_client;			// 存放客户端IP地址、端口

// 消息格式
struct umsg {
	int type;					// 协议(1:登录,2:退出,3:发消息)
	char name[64];				// 用户名字
	char text[512];				// 文本
};

#pragma endregion

#pragma region 依赖函数

// 监听服务器消息
void recvMessage()
{
	while (1){
		umsg msg;
		int ret_recv = recv(
			client, 		// 本地套接字
			(char*)&msg,	// 存放接收的消息
			sizeof(msg),	// 消息大小
			0				// 不指定调用方式
		);
		if (ret_recv <= 0) { cout << "recv failed: " << GetLastError() << endl; break; }
		
		// 打印消息
		cout << msg.name << ": " << msg.text << endl;
	}
}

#pragma endregion

int main()
{
	cout << "我是客户端" << endl;

	// 初始化 WSA ,激活 socket
	WSADATA wsaData;
	if (WSAStartup(
		MAKEWORD(2, 2), 	// 规定 socket 版本
		&wsaData			// 接收 socket 的更多信息
	)) {
		cout << "WSAStartup failed : " << GetLastError() << endl;
	}

	// 初始化 socket、客户端信息
	client = socket(
		AF_INET,		// IPV4
		SOCK_STREAM,	// TCP
		0				// 不指定协议
	);
	sai_client.sin_family = AF_INET;									// IPV4
	inet_pton(AF_INET, "192.168.1.100", &sai_client.sin_addr);			// 服务器 IP地址
	sai_client.sin_port = htons(8090);									// 端口

	// 连接服务器
	int ret_connect = connect(
		client, 					// 本地套接字
		(sockaddr*) &sai_client, 	// 目标
		sizeof(sai_client)
	);if (ret_connect != 0) { cout << "connect failed:" << GetLastError() << endl; }

	// 输入用户名
	umsg msg;
	msg.type = 1;
	string name;
	getline(cin, name);
	strncpy_s(msg.name, sizeof(msg.name), name.c_str(), 64);
	strncpy_s(msg.text, sizeof(msg.text), "", 512);

	// 发送登录消息
	send(
		client,			// 本地套接字
		(char*)&msg,	// 发送的消息
		sizeof(msg),	// 消息大小
		0				// 不指定调用方式
	); 
	int error_send = GetLastError();
	if (error_send != 0) { cout << "send failed:" << error_send << endl; }
	
	// 接收服务器消息
	HANDLE h_recvMes = CreateThread(0, 0, (LPTHREAD_START_ROUTINE)recvMessage, 0, 0, 0);
	if (!h_recvMes) { cout << "CreateThread failed :" << GetLastError() << endl; }

	// 发送消息
	while (1) {
		string content;
		getline(cin, content);

		// 退出消息
		if (content == "quit") {
			msg.type = 2;
			send(
				client,			// 本地套接字
				(char*)&msg,	// 发送的消息
				sizeof(msg),	// 消息大小
				0				// 不指定调用方式
			);
			error_send = GetLastError();
			if (error_send != 0) { cout << "send failed:" << error_send << endl; }
			closesocket(client);
			WSACleanup();
			return 0;
		}
		
		// 会话消息
		msg.type = 3;
		strncpy_s(msg.text, sizeof(msg.text), content.c_str(), 512);
		send(
			client,			// 本体套接字
			(char*)&msg,	// 发送的消息
			sizeof(msg),	// 消息大小
			0				// 不指定调用方式
		);
		error_send = GetLastError();
		if (error_send != 0) { cout << "send failed:" << error_send << endl; }

	}

    getchar();
    return 0;
}
阅读终点,创作起航,您可以撰写心得或摘录文章要点写篇博文。去创作
  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
实现C/C++下TCP服务器/客户端多人聊天室,需要以下步骤: 1. 确定通信协议 在TCP/IP协议中,服务器和客户端之间的通信使用套接字(Socket)实现。服务器和客户端之间的通信协议需要在客户端和服务器之间进行协商,确定信息的格式和传输方式。 2. 设计服务器程序 服务器需要具有以下功能: - 监听客户端的连接请求。 - 接收客户端发送的信息,并将信息转发给其他客户端。 - 维护客户端连接状态,包括处理连接请求、处理断开连接请求等。 3. 设计客户端程序 客户端需要具有以下功能: - 连接服务器。 - 发送消息给服务器。 - 接收服务器转发的其他客户端发送的消息。 - 登录验证。 4. 实现用户账号密码用txt保存并读取 可以使用文件读写API实现用户账号密码用txt保存并读取。具体实现可以在服务器端或客户端实现。 下面是一个简单的C++代码实现多人聊天室的服务器和客户端: 服务器端代码: ```c++ #include <iostream> #include <string> #include <cstring> #include <cstdio> #include <cstdlib> #include <unistd.h> #include <sys/socket.h> #include <arpa/inet.h> #include <pthread.h> #include <map> #define MAX_CLIENT_NUM 100 #define BUFF_SIZE 1024 using namespace std; struct ClientInfo { int sock_fd; string username; }; map<int, ClientInfo> client_list; // 客户端列表 pthread_mutex_t mutex_client_list; // 客户端列表的锁 void send_message(const char* message, int sender_sock_fd) { pthread_mutex_lock(&mutex_client_list); for (auto& client : client_list) { if (client.second.sock_fd != sender_sock_fd) { write(client.second.sock_fd, message, strlen(message)); } } pthread_mutex_unlock(&mutex_client_list); } void* handle_client(void* arg) { int sock_fd = *(int*)arg; char buff[BUFF_SIZE] = {0}; string username; // 接收客户端的用户名 read(sock_fd, buff, BUFF_SIZE); username = buff; pthread_mutex_lock(&mutex_client_list); ClientInfo client_info; client_info.sock_fd = sock_fd; client_info.username = username; client_list.insert(make_pair(sock_fd, client_info)); pthread_mutex_unlock(&mutex_client_list); printf("User %s connected.\n", username.c_str()); // 广播有新用户连接 string message = username + " joined the room.\n"; send_message(message.c_str(), sock_fd); // 循环处理客户端消息 while (true) { memset(buff, 0, sizeof(buff)); int recv_len = read(sock_fd, buff, BUFF_SIZE); if (recv_len <= 0) { // 客户端断开连接 pthread_mutex_lock(&mutex_client_list); client_list.erase(sock_fd); pthread_mutex_unlock(&mutex_client_list); printf("User %s disconnected.\n", username.c_str()); // 广播有用户断开连接 string message = username + " left the room.\n"; send_message(message.c_str(), sock_fd); close(sock_fd); break; } // 广播客户端发送的消息 message = username + ": " + buff; send_message(message.c_str(), sock_fd); } return NULL; } int main(int argc, char* argv[]) { if (argc != 2) { printf("Usage: %s <port>\n", argv[0]); exit(-1); } int server_sock_fd = socket(AF_INET, SOCK_STREAM, 0); if (server_sock_fd < 0) { perror("socket"); exit(-1); } int port = atoi(argv[1]); sockaddr_in server_addr; server_addr.sin_family = AF_INET; server_addr.sin_port = htons(port); server_addr.sin_addr.s_addr = INADDR_ANY; if (bind(server_sock_fd, (sockaddr*)&server_addr, sizeof(server_addr)) < 0) { perror("bind"); exit(-1); } if (listen(server_sock_fd, MAX_CLIENT_NUM) < 0) { perror("listen"); exit(-1); } pthread_mutex_init(&mutex_client_list, NULL); while (true) { sockaddr_in client_addr; socklen_t client_addr_len = sizeof(client_addr); int client_sock_fd = accept(server_sock_fd, (sockaddr*)&client_addr, &client_addr_len); if (client_sock_fd < 0) { perror("accept"); continue; } pthread_t thread_id; pthread_create(&thread_id, NULL, handle_client, &client_sock_fd); pthread_detach(thread_id); } return 0; } ``` 客户端代码: ```c++ #include <iostream> #include <string> #include <cstring> #include <cstdio> #include <cstdlib> #include <unistd.h> #include <sys/socket.h> #include <arpa/inet.h> #define BUFF_SIZE 1024 using namespace std; int main(int argc, char* argv[]) { if (argc != 3) { printf("Usage: %s <ip> <port>\n", argv[0]); exit(-1); } int sock_fd = socket(AF_INET, SOCK_STREAM, 0); if (sock_fd < 0) { perror("socket"); exit(-1); } int port = atoi(argv[2]); sockaddr_in server_addr; server_addr.sin_family = AF_INET; server_addr.sin_port = htons(port); if (inet_pton(AF_INET, argv[1], &server_addr.sin_addr) < 0) { perror("inet_pton"); exit(-1); } if (connect(sock_fd, (sockaddr*)&server_addr, sizeof(server_addr)) < 0) { perror("connect"); exit(-1); } char buff[BUFF_SIZE] = {0}; string username, password; // 登录验证 printf("Please enter your username: "); cin >> username; printf("Please enter your password: "); cin >> password; sprintf(buff, "%s:%s", username.c_str(), password.c_str()); write(sock_fd, buff, strlen(buff)); // 循环处理用户输入和服务器消息 while (true) { fd_set read_set; FD_ZERO(&read_set); FD_SET(STDIN_FILENO, &read_set); FD_SET(sock_fd, &read_set); select(sock_fd + 1, &read_set, NULL, NULL, NULL); if (FD_ISSET(STDIN_FILENO, &read_set)) { // 从标准输入读取用户输入,发送给服务器 string message; getline(cin, message); sprintf(buff, "%s", message.c_str()); write(sock_fd, buff, strlen(buff)); } if (FD_ISSET(sock_fd, &read_set)) { // 从服务器读取消息,输出到标准输出 memset(buff, 0, sizeof(buff)); int recv_len = read(sock_fd, buff, BUFF_SIZE); if (recv_len <= 0) { printf("Disconnected from server.\n"); break; } printf("%s", buff); } } close(sock_fd); return 0; } ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值