Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/124.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 套接字聊天系统-向所有客户端广播_C++_Chat_Winsock - Fatal编程技术网

C++ 套接字聊天系统-向所有客户端广播

C++ 套接字聊天系统-向所有客户端广播,c++,chat,winsock,C++,Chat,Winsock,服务器和客户端之间的通信正常,但服务器不会将客户端消息转发给其他连接的客户端,而只转发给发送方 我希望服务器对传入的消息做出反应,像聊天系统一样向所有客户端广播消息,但保留我的命令系统,不与所有客户端共享,而是与发送方共享 以下是来源: 服务器 /*server*/ #define WIN32_LEAN_AND_MEAN #include <iostream> #include <string> #include <windows.h> #includ

服务器和客户端之间的通信正常,但服务器不会将客户端消息转发给其他连接的客户端,而只转发给发送方

我希望服务器对传入的消息做出反应,像聊天系统一样向所有客户端广播消息,但保留我的命令系统,不与所有客户端共享,而是与发送方共享

以下是来源:

服务器

    /*server*/
#define WIN32_LEAN_AND_MEAN
#include <iostream>
#include <string>
#include <windows.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#include <stdlib.h>
#include <stdio.h>
#include <process.h>

// Need to link with Ws2_32.lib, Mswsock.lib, and Advapi32.lib
#pragma comment (lib, "Ws2_32.lib")
#pragma comment (lib, "Mswsock.lib")
#pragma comment (lib, "AdvApi32.lib")


#define PORT "3490"

#define SERVER "localhost"


#include <time.h>

WSADATA wsa;

SOCKET s , new_socket;

struct sockaddr_in server , client;

int c;

char *message;

std::string line;



DWORD WINAPI ProcessClient (LPVOID lpParameter)
{
    SOCKET AcceptSocket = (SOCKET) lpParameter;

    // Send and receive data.
    int bytesSent;

    int bytesRecv = SOCKET_ERROR;

    char sendbuf[2000]="";
     char sendbuf2[2000]="";

    char recvbuf[2000]="";

    char timebuf[128];

    sprintf(sendbuf, "Hello, it's a test server at %s:%d (commands: 1, 2, exit)\n", SERVER, PORT);

    bytesSent = send( AcceptSocket, sendbuf, strlen(sendbuf), 0);

    if (bytesSent == SOCKET_ERROR)
    {
        printf( "Error at send hello: %ld\n", WSAGetLastError());
        goto fin;
    }

    while (1)
    {
        _strtime( timebuf );
        ZeroMemory (recvbuf, sizeof(recvbuf));

        bytesRecv = recv( AcceptSocket, recvbuf, 32, 0);

        printf( "%s Client said: %s\n", timebuf, recvbuf);



        sprintf(sendbuf, "%s Client said: %s\n", timebuf, recvbuf);
        bytesSent = send( AcceptSocket, sendbuf, strlen(sendbuf), 0);


        if (strcmp(recvbuf, "1") == 0)
        {
            sprintf(sendbuf, "You typed ONE\n");
            //printf("Sent '%s'\n", sendbuf);
            bytesSent = send( AcceptSocket, sendbuf, strlen(sendbuf), 0);

            if (bytesSent == SOCKET_ERROR)
            {
                printf( "Error at send: %ld\n", WSAGetLastError());
                goto fin;
            }
        }
        else if (strcmp(recvbuf, "2") == 0)
        {
            sprintf(sendbuf, "You typed TWO\n");
            //printf("Sent '%s'\n", sendbuf);
            bytesSent = send( AcceptSocket, sendbuf, strlen(sendbuf), 0);

            if (bytesSent == SOCKET_ERROR)
            {
                printf( "Error at send: %ld\n", WSAGetLastError());
                goto fin;
            }
        }
        else if (strcmp(recvbuf, "exit") == 0)
        {
            printf( "Client has logged out\n", WSAGetLastError());
            goto fin;
        }
        else
        {
           // sprintf(sendbuf, "unknown command\n");
            //printf("Sent '%s'\n", sendbuf);
           //  bytesSent = send( AcceptSocket, sendbuf, strlen(sendbuf), 0);

            if (bytesSent == SOCKET_ERROR)
            {
               // printf( "Error at send: %ld\n", WSAGetLastError());
                goto fin;
            }
        }
    }

fin:
    printf("Client processed\n");

    closesocket(AcceptSocket);
    return 0;
}




int main(int argc , char *argv[])
{

    std::cout << ("\nInitialising Winsock...");

    if (WSAStartup(MAKEWORD(2,2),&wsa) != 0)
    {
        std::cout << ("Failed. Error Code : %d",WSAGetLastError());
        return 1;
    }

    printf("Initialised.\n");

    //Create a socket
    if((s = socket(AF_INET , SOCK_STREAM , 0 )) == INVALID_SOCKET)
    {
        std::cout << ("Could not create socket : %d" , WSAGetLastError());
    }

    std::cout << ("Socket created.\n");

    //Prepare the sockaddr_in structure
    server.sin_family = AF_INET;
    server.sin_addr.s_addr = INADDR_ANY;
    server.sin_port = htons( 3490 );

    //Bind
    if( bind(s ,(struct sockaddr *)&server , sizeof(server)) == SOCKET_ERROR)
    {
        std::cout << ("Bind failed with error code : %d" , WSAGetLastError());
        exit(EXIT_FAILURE);
    }

    puts("Bind done");



    //Listen to incoming connections
    listen(s , 3);



    //Accept and incoming connection
    std::cout << ("Waiting for incoming connections...");

    c = sizeof(struct sockaddr_in);

    while(true){



  while((new_socket = accept(s , (struct sockaddr *)&client, &c)) != INVALID_SOCKET) {
        // Create a new thread for the accepted client (also pass the accepted client socket).
       printf( "Client Connected.\n");

        DWORD dwThreadId;
        CreateThread (NULL, 0, ProcessClient, (LPVOID) new_socket, 0, &dwThreadId);
    }





       }

    if (new_socket == INVALID_SOCKET)
    {
        std::cout << ("accept failed with error code : %d" , WSAGetLastError());
        return 1;
    }

    closesocket(s);
    WSACleanup();

    return 0;
}
/*服务器*/
#定义WIN32_精益_和_平均值
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
//需要链接到Ws2_32.lib、Mswsock.lib和Advapi32.lib
#pragma注释(lib,“Ws2_32.lib”)
#pragma注释(lib,“Mswsock.lib”)
#pragma注释(lib,“AdvApi32.lib”)
#定义端口“3490”
#定义服务器“localhost”
#包括
WSADATA wsa;
插座s,新的_插座;
服务器、客户端中的结构sockaddr_;
INTC;
字符*消息;
std::字符串行;
DWORD WINAPI ProcessClient(LPVOID lpParameter)
{
SOCKET AcceptSocket=(SOCKET)lp参数;
//发送和接收数据。
int bytesSent;
int bytesRecv=套接字错误;
char sendbuf[2000]=“”;
char sendbuf2[2000]=“”;
char recvbuf[2000]=“”;
char-timebuf[128];
sprintf(sendbuf,“您好,这是一个测试服务器,位于%s:%d(命令:1,2,退出)\n)”,服务器,端口;
bytesSent=send(AcceptSocket,sendbuf,strlen(sendbuf),0);
if(bytesSent==SOCKET\u错误)
{
printf(“发送hello时出错:%ld\n”,WSAGetLastError());
后藤鳍;
}
而(1)
{
_strtime(timebuf);
零内存(recvbuf,sizeof(recvbuf));
bytesRecv=recv(AcceptSocket,recvbuf,32,0);
printf(“%s客户端说:%s\n”,timebuf,recvbuf);
sprintf(sendbuf,“%s客户端说:%s\n”,timebuf,recvbuf);
bytesSent=send(AcceptSocket,sendbuf,strlen(sendbuf),0);
如果(strcmp(recvbuf,“1”)==0)
{
sprintf(sendbuf,“您键入了一个”\n);
//printf(“已发送“%s”\n”,sendbuf);
bytesSent=send(AcceptSocket,sendbuf,strlen(sendbuf),0);
if(bytesSent==SOCKET\u错误)
{
printf(“发送时出错:%ld\n”,WSAGetLastError());
后藤鳍;
}
}
否则如果(strcmp(recvbuf,“2”)==0)
{
sprintf(sendbuf,“您键入了两个\n”);
//printf(“已发送“%s”\n”,sendbuf);
bytesSent=send(AcceptSocket,sendbuf,strlen(sendbuf),0);
if(bytesSent==SOCKET\u错误)
{
printf(“发送时出错:%ld\n”,WSAGetLastError());
后藤鳍;
}
}
否则如果(strcmp(recvbuf,“退出”)==0)
{
printf(“客户端已注销”,WSAGetLastError());
后藤鳍;
}
其他的
{
//sprintf(sendbuf,“未知命令”);
//printf(“已发送“%s”\n”,sendbuf);
//bytesSent=send(AcceptSocket,sendbuf,strlen(sendbuf),0);
if(bytesSent==SOCKET\u错误)
{
//printf(“发送时出错:%ld\n”,WSAGetLastError());
后藤鳍;
}
}
}
鳍:
printf(“已处理的客户端”);
闭合插座(接受插座);
返回0;
}
int main(int argc,char*argv[])
{

std::cout如果您需要服务器与多个客户端通信,那么您需要某种类型的所有已连接客户端的集合。这样就很容易发送到所有连接,或者发送到除原始连接之外的所有连接

<>如何做到这一点在C和C++之间有很大的不同,但是C++对结构和./p>进行了研究。
在伪代码中,它是这样的:

while (run_server)
{
    poll_all_connections();

    if (have_new_connection())
    {
        accept_new_connection();
        add_connection_in_collection();
    }
    else
    {
        for (connection in all_connections())
        {
            if (have_input(connection))
            {
                input = read_from_connection(connection);

                for (send_to in all_connections())
                    write_to_connection(connection, input)
            }
        }
    }
}
如果实现上述伪代码,则来自任何连接的输入都将发送到所有连接


如果连接中断(错误或断开连接),请不要忘记从集合中删除连接。

您必须维护所有客户端套接字连接的列表,然后将数据逐个发送到每个客户端

或者,您可以使用线程来实现这一点,如下所示:-

 Server-thread()
 {
   while(true)
    {
       /// Accept Connection in ClientSocket. 

       HandleClient-Thread(ClientSocket)  ; // launch a thread for each client .
     }

  } 

  HandleClient-Thread(ClientSocket)
   {
     // handle this client here 

   }

C++的方法会很好的!如果你不介意改变你的工作方式,那么请你说“萨拉拉森”我添加了一些伪代码来显示一种处理方法。我在寻找什么!我很高兴有人支持我!* -但是我很难理解这个伪例子,你能……如果你不介意的话。将它植入我发布的服务器中,这样我就可以看到并了解它是如何正确完成的。`@SarahLarsen如果你只搜索一点,就会有很多聊天服务器教程,其中包含完整的代码示例。我发现你的方法更好了,但我不知道如何将它植入服务器中,如果你能做到这一点,那对我来说将意味着整个世界“我马上就接受你的答案……请你能一步一步地给我看,或者把它植入服务器中吗”?这会很有帮助,而且更容易理解:)@你说的是做你的家庭作业。只需维护一个包含所有传入连接的数组,然后从一个循环将数据一个接一个地发送到所有这些@Joachim Pileborg即可向你展示。我只是礼貌地问你是否介意向我展示我如何理解它,它将帮助fture中的任何人…这方面没有家庭作业…我只是不知道如何做我编辑了我的答案,给你一个新的想法来实现这一点。
 Server-thread()
 {
   while(true)
    {
       /// Accept Connection in ClientSocket. 

       HandleClient-Thread(ClientSocket)  ; // launch a thread for each client .
     }

  } 

  HandleClient-Thread(ClientSocket)
   {
     // handle this client here 

   }