網站首頁 編程語言 正文
TIPS:以下使用CMake項目進行開發。關于何為CMake,鏈接:https://www.jb51.net/article/247089.htm
簡單聊天室效果展示
簡單聊天室服務端源碼(使用select模型)
// Server0327.cpp: 定義應用程序的入口點。
//
#include "Server0327.h"
#include <WinSock2.h>
#include <vector>
#pragma comment(lib,"ws2_32.lib")
using namespace std;
class TcpServer
{
public:
?? ?bool Listen(const char* ip, int port)
?? ?{
?? ??? ?//創建socket
?? ??? ?_serverSock = socket(AF_INET, SOCK_STREAM, 0);
?? ??? ?if (INVALID_SOCKET == _serverSock)
?? ??? ??? ?goto Exit;
?? ??? ?//綁定IP和端口號
?? ??? ?SOCKADDR_IN addr;
?? ??? ?addr.sin_addr.s_addr = inet_addr(ip);
?? ??? ?addr.sin_family = AF_INET;
?? ??? ?addr.sin_port = htons(port);
?? ??? ?if (INVALID_SOCKET == bind(_serverSock, (sockaddr*)&addr, sizeof(SOCKADDR_IN)))
?? ??? ??? ?goto Exit;
?? ??? ?//監聽端口
?? ??? ?if (INVALID_SOCKET == listen(_serverSock, 255))
?? ??? ??? ?goto Exit;
?? ??? ?return true;
?? ?Exit:
?? ??? ?closesocket(_serverSock);
?? ??? ?_serverSock = INVALID_SOCKET;
?? ??? ?return false;
?? ?}
?? ?void Update()
?? ?{
?? ??? ?FD_SET reads;
?? ??? ?FD_ZERO(&reads);
?? ??? ?FD_SET(_serverSock, &reads);
?? ??? ?for (auto&& clientSock : _clientSocks)
?? ??? ??? ?FD_SET(clientSock, &reads);
?? ??? ?int nRet = select(0, &reads, nullptr, nullptr, nullptr);
?? ??? ?if (nRet > 0)
?? ??? ?{
?? ??? ??? ?if (FD_ISSET(_serverSock, &reads))
?? ??? ??? ??? ?Accept();
?? ??? ??? ?else
?? ??? ??? ?{
?? ??? ??? ??? ?for (int i = 0; i < _clientSocks.size(); i++)
?? ??? ??? ??? ?{
?? ??? ??? ??? ??? ?if (FD_ISSET(_clientSocks[i], &reads))
?? ??? ??? ??? ??? ?{
?? ??? ??? ??? ??? ??? ?char buf[1024]{ 0 };
?? ??? ??? ??? ??? ??? ?int nRecv = recv(_clientSocks[i], buf, 1024, 0);
?? ??? ??? ??? ??? ??? ?if (nRecv > 0)
?? ??? ??? ??? ??? ??? ??? ?OnNetMsg(_clientSocks[i], buf, sizeof(buf));
?? ??? ??? ??? ??? ??? ?if (nRecv <= 0)
?? ??? ??? ??? ??? ??? ?{
?? ??? ??? ??? ??? ??? ??? ?closesocket(_clientSocks[i]);
?? ??? ??? ??? ??? ??? ??? ?OnDisConnect(_clientSocks[i]);
?? ??? ??? ??? ??? ??? ??? ?_clientSocks.erase(_clientSocks.begin() + i);
?? ??? ??? ??? ??? ??? ??? ?continue;
?? ??? ??? ??? ??? ??? ?}
?? ??? ??? ??? ??? ?}
?? ??? ??? ??? ?}
?? ??? ??? ?}
?? ??? ?}
?? ?}
?? ?void Accept()
?? ?{
?? ??? ?SOCKADDR_IN clientAddr;
?? ??? ?int clientAddrLen = sizeof(clientAddr);
?? ??? ?SOCKET clientSock = accept(_serverSock, (sockaddr*)&clientAddr, &clientAddrLen);
?? ??? ?if (INVALID_SOCKET != clientSock)
?? ??? ?{
?? ??? ??? ?_clientSocks.push_back(clientSock);
?? ??? ??? ?OnConnect(clientSock);
?? ??? ?}
?? ?}
?? ?void OnConnect(SOCKET clientSock)
?? ?{
?? ??? ?printf("%d 客戶端連接\n", clientSock);
?? ?}
?? ?int OnNetMsg(SOCKET clientSock, const char* buff, int len)
?? ?{
?? ??? ?printf("%d == %s\n", clientSock, buff);
?? ??? ?for (auto&& clientSock : _clientSocks)
?? ??? ??? ?send(clientSock, buff, len, 0);
?? ??? ?return len;
?? ?}
?? ?void OnDisConnect(SOCKET sock)
?? ?{
?? ??? ?printf("%d==客戶端斷開連接\n", sock);
?? ?}
private:
?? ?SOCKET _serverSock;
?? ?vector<SOCKET> _clientSocks;
};
int main()
{
?? ?WSADATA wsa;
?? ?WSAStartup(MAKEWORD(2, 2), &wsa);
?? ?TcpServer server;
?? ?server.Listen("0.0.0.0", 7890);
?? ?while (true)
?? ??? ?server.Update();
?? ?WSACleanup();
?? ?return 0;
}
簡單聊天室客戶端源碼(使用多線程)
// CMakeClient0331.cpp: 定義應用程序的入口點。
//
#include "CMakeClient0331.h"
#include<iostream>
#include<WinSock2.h>
#include<thread>
#pragma comment(lib,"ws2_32.lib")
int main()
{
?? ?WSADATA wsaData;
?? ?WSAStartup(MAKEWORD(2, 2), &wsaData);
?? ?SOCKET clientSock = socket(AF_INET, SOCK_STREAM, 0);
?? ?if (INVALID_SOCKET == clientSock)
?? ?{
?? ??? ?closesocket(clientSock);
?? ??? ?WSACleanup();
?? ??? ?return 0;
?? ?}
?? ?SOCKADDR_IN serverAddr;
?? ?serverAddr.sin_family = AF_INET;
?? ?serverAddr.sin_addr.s_addr = inet_addr("127.0.0.1");
?? ?serverAddr.sin_port = htons(7890);
?? ?if (INVALID_SOCKET == connect(clientSock, (sockaddr*)&serverAddr, sizeof(SOCKADDR_IN)))
?? ?{
?? ??? ?closesocket(clientSock);
?? ??? ?WSACleanup();
?? ??? ?return 0;
?? ?}
?? ?std::cout << "已連接服務端" << std::endl;
?? ?std::thread t([&clientSock] {
?? ??? ?while (true)
?? ??? ?{
?? ??? ??? ?char buf[1024]{ 0 };
?? ??? ??? ?int nRecvLen = recv(clientSock, buf, 1024, 0);
?? ??? ??? ?if (nRecvLen <= 0)
?? ??? ??? ??? ?break;
?? ??? ??? ?std::cout << "接收數據長度:" << nRecvLen << " 接受數據:" << buf << std::endl;
?? ??? ?}
?? ??? ?});
?? ?t.detach();
?? ?while (true)
?? ?{
?? ??? ?char buf[1024]{ 0 };
?? ??? ?std::cin >> buf;
?? ??? ?if (buf[0] == 'q')break;
?? ??? ?int nSendLen = send(clientSock, buf, sizeof(buf), 0);
?? ?}
?? ?closesocket(clientSock);
?? ?WSACleanup();
?? ?return 0;
}
原文鏈接:https://blog.csdn.net/qq135595696/article/details/124153499
相關推薦
- 2022-08-04 Python+NumPy繪制常見曲線的方法詳解_python
- 2023-10-17 uniapp通過功能性編碼跳轉到原生的app頁面
- 2022-05-25 python?序列去重并保持原始順序操作_python
- 2022-04-21 Android圖表庫HelloChart繪制多折線圖_Android
- 2022-12-24 python的open函數常見用法_python
- 2022-11-16 anaconda打開閃退的解決過程_python
- 2023-01-12 利用C#實現進程管理器_C#教程
- 2022-07-20 Android?shape與selector標簽使用詳解_Android
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支