C++멀 티 채 팅 실현

19135 단어 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;
}
클 라 이언 트 코드:

// Test_Console_2.cpp :       "main"   。             。
//

#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
서버 코드:

// 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];   //     
};

//      
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;
}
클 라 이언 트 코드:

// Test_Console_2.cpp :       "main"   。             。
//

#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;
}
효과 그림:

이상 이 바로 본 고의 모든 내용 입 니 다.여러분 의 학습 에 도움 이 되 고 저 희 를 많이 응원 해 주 셨 으 면 좋 겠 습 니 다.

좋은 웹페이지 즐겨찾기