UDP消息服务器C ++,两个客户端之间的通信 [英] Udp messaging server c++, communication between two clients

查看:349
本文介绍了UDP消息服务器C ++,两个客户端之间的通信的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我通过UDP服务器有两个UDP客户端之间的通信问题(A->服务器 - > B)。
首先,我客户的address_in保存到一个HashMap,那么客户端发送给客户B的一些消息。每一件事情是右(I记录连通的流动),除了该服务器只发送消息到当前请求客户机(客户端),而使用客户端B的地址。这里是我的code:

 私人:
        性病::地图< INT,SOCKADDR_IN> ids_clients;
        静态INT插座;        静态无效sig_handler(INT预兆报){
                如果(SIGNO == SIGKILL){
                        关闭(插座);
                        的printf(停止\\ n);
                }
        }        无效监视器(){
                诠释计数;
                socklen_t的addr_size = sizeof的(SOCKADDR_IN);
                结构sockaddr_in的地址;
                性病::地图< INT,SOCKADDR_IN> ::迭代器client_it;
                缓冲缓冲;
                消息消息;
                而(真){
                        buffer.reset();
                        如果((计数= recvfrom的(插座,buffer.getBuffer(),buffer.getCapacity(),MSG_TRUNC,(结构sockaddr *)及地址,&放大器; addr_size))== - 1){
                                PERROR(网络错误。\\ n!);
                                打破;
                        }
                        如果(计数> message.getHeaderSize()){
                                message.deserialize(安培;缓冲区,计数);
                                INT ID = message.getTag();
                                的printf(ID数:%d \\ n,身份证);
                                开关(message.getType()){
                                        案件消息::类型:: CONN:
                                        {
                                                //保存客户端地址
                                                的printf(佐克数:%d,ID:%d个,IP:%s端口数:%d \\ n,插座,ID,INET_NTOA(address.sin_addr),address.sin_port);
                                                ids_clients [ID] =地址;
                                                message.setTag(消息:: code :: OK);
                                                message.serialize(安培;缓冲区);
                                                如果(SENDTO(插座,buffer.getBuffer(),buffer.getSize(),0,(结构sockaddr *)及地址,addr_size)== - 1){
                                                        ids_clients.erase(ids_clients.find(ID));
                                                        的printf(!经过身份验证 - 客户端:%s的:%D:不能响应\\ n,INET_NTOA(address.sin_addr),ntohs和(address.sin_port));
                                                        继续;
                                                }
                                                打破;
                                        }
                                        案件消息::类型:: MEDIA:
                                        {
                                                从目前的客户端//发送到客户端具有ID = message.getTag();
                                                的printf(佐克数:%d,ID:%d个,IP:%s端口数:%d \\ n,插座,ID,INET_NTOA(address.sin_addr),address.sin_port);
                                                如果(message.getChannel()==消息::频道::单){
                                                        client_it = ids_clients.find(ID);
                                                        如果(client_it!= ids_clients.end()){
                                                                的printf(ID:%d个,IP:%s端口数:%d \\ n,message.getSeqNo(),INET_NTOA(client_it-> second.sin_addr),client_it-> second.sin_port);
                                                                的printf(佐克:%D,SRC ID:%D,TO ID:%d个\\ N,插座,message.getSeqNo(),身份证);
                                                                message.serialize(安培;缓冲区);
                                                                如果(SENDTO(插座,buffer.getBuffer(),buffer.getSize(),0,(结构sockaddr *)及(client_it->第二个)的sizeof(client_it->第二个))== -1){
                                                                        ids_clients.erase(client_it);
                                                                        的printf(媒体包 - 客户端:%s的:%D:无法达到\\ n!,INET_NTOA(client_it-> second.sin_addr),ntohs和(client_it-> second.sin_port));
                                                                        继续;
                                                                }
                                                        }
                                                }
                                                打破;
                                        }
                                }
                        }其他{
                                //回声服务器
                                SENDTO(插座,buffer.getBuffer(),计数,0,(结构sockaddr *)及地址,addr_size);
                        }
                }
        }
上市:        无效启动(INT端口){
                信号(SIGKILL,sig_handler);
                结构SOCKADDR_IN罪。
                插座= ::插座(AF_INET,SOCK_DGRAM,IPPROTO_UDP);
                诠释MPS = PGK_MAX_SIZE;
                如果(setsockopt的(插座,SOL_SOCKET,SO_RCVBUF,&安培; MPS,的sizeof(MPS))== -1){
                        PERROR(SO_RCVBUF \\ n);
                        出口(EXIT_FAILURE);
                }
                memset的(安培;罪,0,sizeof的(罪));
                sin.sin_family = AF_INET;
                sin.sin_addr.s_addr = INADDR_ANY;
                sin.sin_port = htons(端口);
                如果(绑定(插座,(结构sockaddr *)及罪的sizeof(SIN))){
                        PERROR(绑定()\\ n);
                        出口(EXIT_FAILURE);
                }
                的printf(开始:端口%d的\\ n,口);
                监控();
                关闭(插座);
                的printf(停止\\ n);
        }
};
int服务器::插座;

请帮忙,
谢谢!


解决方案

 如果(计数> message.getHeaderSize()){

如果这是假的,是不是失败于:

  //回声服务器
SENDTO(插座,buffer.getBuffer(),计数,0,(结构sockaddr *)及地址,addr_size);

刚刚发回?

我们错过code的不少。你需要拿出一个小的,独立的可重复执行的测试案例,如果你想人来帮助你。请参阅以下链接的帮助将一起。

http://sscce.org/

I have a problem on communication between two udp client via udp server(a->server->b). First I save the clients's address_in to a hashmap, Then client a send to client b some messages. Every thing is right(I logged the flow of communicating) except that server only send message to current requested client(client a) while using address of client b. Here is my code:

private:
        std::map<int, sockaddr_in> ids_clients;
        static int socket;

        static void sig_handler(int signo) {
                if (signo == SIGKILL) {
                        close(socket);
                        printf("stopped\n");
                }
        }

        void monitor() {
                int count;
                socklen_t addr_size = sizeof (sockaddr_in);
                struct sockaddr_in address;
                std::map<int, sockaddr_in>::iterator client_it;
                Buffer buffer;
                Message message;
                while (true) {
                        buffer.reset();
                        if ((count = recvfrom(socket, buffer.getBuffer(), buffer.getCapacity(), MSG_TRUNC, (struct sockaddr *) &address, &addr_size)) == -1) {
                                perror("network error!\n");
                                break;
                        }
                        if (count > message.getHeaderSize()) {
                                message.deserialize(&buffer, count);
                                int id = message.getTag();
                                printf("id: %d\n", id);
                                switch (message.getType()) {
                                        case Message::Type::CONN:
                                        {
                                                //Save client address
                                                printf("SOCK: %d, ID: %d, IP: %s, PORT: %d\n", socket, id, inet_ntoa(address.sin_addr), address.sin_port);
                                                ids_clients[id] = address;
                                                message.setTag(Message::Code::OK);
                                                message.serialize(&buffer);
                                                if (sendto(socket, buffer.getBuffer(), buffer.getSize(), 0, (struct sockaddr *) &address, addr_size) == -1) {
                                                        ids_clients.erase(ids_clients.find(id));
                                                        printf("Authenticated - client: %s:%d: could not response!\n", inet_ntoa(address.sin_addr), ntohs(address.sin_port));
                                                        continue;
                                                }
                                                break;
                                        }
                                        case Message::Type::MEDIA:
                                        {
                                                //Send from current client to the client has id = message.getTag();
                                                printf("SOCK: %d, ID: %d, IP: %s, PORT: %d\n", socket, id, inet_ntoa(address.sin_addr), address.sin_port);
                                                if (message.getChannel() == Message::Channel::SINGLE) {
                                                        client_it = ids_clients.find(id);
                                                        if (client_it != ids_clients.end()) {
                                                                printf("ID: %d, IP: %s, PORT: %d\n", message.getSeqNo(), inet_ntoa(client_it->second.sin_addr), client_it->second.sin_port);
                                                                printf("SOCK: %d, SRC ID:%d, TO ID: %d\n", socket, message.getSeqNo(), id);
                                                                message.serialize(&buffer);
                                                                if (sendto(socket, buffer.getBuffer(), buffer.getSize(), 0, (struct sockaddr *) &(client_it->second), sizeof (client_it->second)) == -1) {
                                                                        ids_clients.erase(client_it);
                                                                        printf("Media package - client: %s:%d: could not reach!\n", inet_ntoa(client_it->second.sin_addr), ntohs(client_it->second.sin_port));
                                                                        continue;
                                                                }
                                                        }
                                                }
                                                break;
                                        }
                                }
                        } else {
                                //echo server
                                sendto(socket, buffer.getBuffer(), count, 0, (struct sockaddr *) &address, addr_size);
                        }
                }
        }
public:

        void start(int port) {
                signal(SIGKILL, sig_handler);
                struct sockaddr_in sin;
                socket = ::socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
                int mps = PGK_MAX_SIZE;
                if (setsockopt(socket, SOL_SOCKET, SO_RCVBUF, &mps, sizeof (mps)) == -1) {
                        perror("SO_RCVBUF\n");
                        exit(EXIT_FAILURE);
                }
                memset(&sin, 0, sizeof (sin));
                sin.sin_family = AF_INET;
                sin.sin_addr.s_addr = INADDR_ANY;
                sin.sin_port = htons(port);
                if (bind(socket, (struct sockaddr *) &sin, sizeof (sin))) {
                        perror("bind()\n");
                        exit(EXIT_FAILURE);
                }
                printf("started: port %d\n", port);
                monitor();
                close(socket);
                printf("stopped\n");
        }
};
int Server::socket;

Please help, Thank you!

解决方案

if (count > message.getHeaderSize()) {

if this is false, doesn't it fall through to:

//echo server
sendto(socket, buffer.getBuffer(), count, 0, (struct sockaddr *) &address, addr_size);

which just sends it back?

We're missing a LOT of code. You need to come up with a small, self contained reproduceable test case if you want people to help you. Please see the link below for help putting that together.

http://sscce.org/

这篇关于UDP消息服务器C ++,两个客户端之间的通信的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆