【问题标题】:C++ multi client chat using TCP socket使用 TCP 套接字的 C++ 多客户端聊天
【发布时间】:2018-01-25 13:49:55
【问题描述】:

我正在尝试使用 TCP 套接字在 C++ 中进行多客户端聊天。 我已经从this site下载了socket实现的源代码。

问题是当我尝试从客户端向服务器发送消息时, 我从服务器收到的“ecko”是无穷无尽的空格字符串。

我尝试调试客户端代码,客户端正确读取输入。 在前几条消息中,服务器将他的消息发送回客户端, 但经过几条消息后,客户端会返回无尽的空间。 我尝试使用 memset 进行无效化(在所有数组中置零),但更糟糕的是,服务器根本不接收消息。

不胜感激(:

这是服务器端:

 #include "PracticalSocket.h"
#include <stdio.h>
#include <process.h>
#include <Windows.h>
using namespace std;
#pragma comment(lib,"ws2_32.lib")


TCPSocket* MyClients[20];
int ClientCount = 0;

 void connectCLient(void* pValue){  
    int nI,Flag;
    char st[1024];
    //memset(st,0,1024); // doing problems
    TCPSocket* pServerClient = (TCPSocket*)pValue;  
    MyClients[ClientCount] = pServerClient;
    ClientCount++;
    try{
        while (true)
        {
             Flag = pServerClient->recv(st,strlen(st));
             if(Flag>1){
                printf("%s\n",st);
                for(nI = 0; nI< ClientCount ; nI++){
                    MyClients[nI]->send(st,strlen(st)+1);
             }
        }


        }
    }
    catch(...){
        puts("one client lefttt");
    }
 }

int main(int argc, char* argv[])
{
    TCPServerSocket* pServer = new TCPServerSocket(8546);
    int nClientCounter = 0;
    printf("Start TCP Server ... on Port %d\n", 8546);

    try{
        while(true)
        {

            printf("Wait for new TCP Clients ... \n");
            TCPSocket* pClient = pServer->accept();     
            _beginthread(connectCLient,0,(void*)pClient);
            printf("Client %d Connected ... \n", ++nClientCounter);
        }
    }
    catch(...){
        puts("one client left");
    }

    return 0;
}

这是客户端:

#include "PracticalSocket.h"
#include <stdio.h>
#include <process.h>
#include <Windows.h>
using namespace std;
#pragma comment (lib, "ws2_32.lib")


void ReciveMessages(void * pValue ){
    char recvM[1024];
    TCPSocket* pClient = (TCPSocket*)pValue;
    while(true){
        pClient->recv(recvM,strlen(recvM));
        printf("%s\n",recvM);
    }
}


int main(int argc, char* argv[])
{
    try
    {
        TCPSocket * cClient = new TCPSocket();
        cClient->connect("127.0.0.1",8546);
        _beginthread(ReciveMessages,0,(void*)cClient);
        char st[1024];
        memset(st,0,1024);
        while(true)
        {

            printf("Press Text -->");
            fgets(st, sizeof st, stdin);
            cClient->send(st,strlen(st)+2); 
        }
    }
    catch(...)
    {
        printf("Socket Error..!");
        system("pause");//run cmd comment - stop the system
    }
    return 0;
}

【问题讨论】:

  • recv(st,strlen(st));字符串可能有多长?
  • 字符串的大小加1,(最后是0)
  • strlen 给出字符串的当前大小,而不是最大大小。 recv 也没有添加换行符或空终止符。

标签: c++ sockets tcp


【解决方案1】:

代码有几个错误:

MyClients[ClientCount] = pServerClient;
ClientCount++;

由于上述情况发生在不同的线程中,ClientCount++ 是非原子的并且会导致竞争条件。将ClientCount 设为原子或在一个服务器线程中执行此操作。


在:

Flag = pServerClient->recv(st,strlen(st));
if(Flag>1) {
    printf("%s\n",st);
    for(nI = 0; nI< ClientCount ; nI++)
        MyClients[nI]->send(st,strlen(st)+1);

st 不以\0 结尾,因为它可以是部分读取,所以strlen(st) 返回错误的结果。修复:

ssize_t received = pServerClient->recv(st, sizeof st - 1);
if(received > 0) {
    st[received] = 0; // Zero-terminate.        
    printf("%s\n", st);
    for(nI = 0; nI< ClientCount ; nI++)
        MyClients[nI]->send(st, received);

类似问题:

pClient->recv(recvM,strlen(recvM));
printf("%s\n",recvM);

修复:

ssize_t received = pClient->recv(recvM, sizeof recvM - 1);
if(received > 0) {
    recvM[received] = 0;
    printf("%s\n",recvM);
}

在:

 cClient->send(st,strlen(st)+2); 

发送零终止符没有意义:

 cClient->send(st, strlen(st)); 

TCP 是一种流协议,这意味着sendrecv 可以发送/接收部分数据并且没有消息边界。你可以delimit your messages

【讨论】:

  • 非常感谢!!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-11-06
  • 1970-01-01
  • 1970-01-01
  • 2016-08-03
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多