同一台计算机上的UDP连接。 1服务器。多个客户

问题描述:

工作Qt框架..,需要得到给出requiremets同一台计算机上的UDP连接。 1服务器。多个客户

的解决方案我已经在一台服务器和2个客户端我的电脑: IP1,IP2,IP3是端口。

我的服务器上IP1听,端口号9999 我要发送数据(数据包)到服务器,然后服务器需要我的客户进行回应。 所以我可以知道客户端IP地址和客户端端口号。

客户端IP地址和端口如何知道服务器?,这是获取响应回到客户端所必需的。

注意:我在同一台PC上运行server,client1和client2。

+0

(IP地址)分配给每个设备的数字标签.. – Ashif

+0

所以如何做我想做什么?我想要一台PC上的许多客户端和服务器。我应该给他们每个人不同的端口号码吗? ,但我想他们每个人给一个不同的IP地址。那可能吗 ? –

+0

客户端从不侦听IP,客户端连接到服务器,对于该客户端主要需要服务器的IP和侦听端口。 – Ashif

不确定Qt框架,但使用正常的套接字命令bind到特定的IP和端口。

handle = socket(AF_INET, SOCK_DGRAM, 0); 

// my local computer 
struct sockaddr_in addr_loc; 
memset(&addr_loc, 0, sizeof(addr_loc)); 
addr_loc.sin_family = AF_INET; 
addr_loc.sin_port = htons(localPort); 
addr_loc.sin_addr.s_addr = htonl(localAddr); 
bind(handle, (struct sockaddr*)&addr_loc, sizeof(addr_loc)); 

// the remote location 
struct sockaddr_in addr_rem; 
memset(&addr_rem, 0, sizeof(addr_rem)); 
addr_rem.sin_family = AF_INET; 
addr_rem.sin_port = htons(remotePort); 
addr_rem.sin_addr.s_addr = htonl(remoteAddr); 
sendto(handle, packetData, packetLength, 0, (struct sockaddr *)&addr_rem, sizeof(addr_rem)); 
+0

为TCP没有问题,但对于UDP,我想让服务器知道我的IP地址,以便他在同一地址回复我。 但我运行时,所有的客户端和服务器获得相同的IP地址。我可以采用某种改变 –

+1

你客户端的地址在'recvfrom' – mark

+1

,但如果我有一台电脑,服务器和客户端都具有相同的IP地址。所以我怎么能区分2 –

,你将有服务器监听本地主机,127.0.0.1,然后每个客户端将连接到本地主机(127.0.0.1),该服务器监听端口上。在这里,我将展示它的外观。

服务器的代码可能是这样的:

#include <unistd.h> 
#include <sys/types.h> 
#include <sys/socket.h> 
#include <netinet/in.h> 
#include <arpa/inet.h> 
#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 
#include <netdb.h> 

int main() { 
    struct addrinfo hints, *res; 
    int sockfd; 
    int byte_count; 
    socklen_t fromlen; 
    struct sockaddr_storage addr; 
    char buf[512]; 
    char ipstr[INET6_ADDRSTRLEN]; 

    // get host info, make socket, bind it to port 9999 
    memset(&hints, 0, sizeof hints); 
    hints.ai_family = AF_UNSPEC; // use IPv4 or IPv6, whichever 
    hints.ai_socktype = SOCK_DGRAM; 
    hints.ai_flags = AI_PASSIVE; 
    getaddrinfo(NULL, "9999", &hints, &res); 
    sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol); 
    bind(sockfd, res->ai_addr, res->ai_addrlen); 

    // no need to accept(), just recvfrom(): 
    fromlen = sizeof addr; 
    byte_count = recvfrom(sockfd, buf, sizeof buf, 0, (sockaddr*)&addr, &fromlen); 

    printf("recv()'d %d bytes of data in buf\n", byte_count); 
    printf("from IP address %s\n", 
      inet_ntop(addr.ss_family, 
      (const void*)(&((struct sockaddr_in *) &addr)->sin_addr), ipstr, sizeof ipstr)); 

    return 0; 
} 

你可以尝试在该服务器通过NC与-vu选项监听终端:

[email protected]:~# nc -vu localhost 9999 

,应该从这样的服务器获得的输出:

recv()'d 29 bytes of data in buf 
from IP address 127.0.0.1 

客户端代码:

#define DEST_PORT 9999 
#define DEST_IP "127.0.0.1" 

int main(int argc, char** argv) { 
    char *secret_message = "The Cheese is in The Toaster"; 

    int dgram_socket; 
    struct sockaddr_in dest_addr; 

    // now with UDP datagram sockets: 
    // datagram sockets and recvfrom() 
    dest_addr.sin_family = AF_INET; 
    /* short, network byte order */ 
    dest_addr.sin_port = htons(DEST_PORT); 
    dest_addr.sin_addr.s_addr = inet_addr(DEST_IP); 

    /* zero the rest of the struct */ 
    memset(&(dest_addr.sin_zero), 0, 8); 

    dgram_socket = socket(dest_addr.sin_family, SOCK_DGRAM, 0); 


    // send secret message normally: 
    sendto(dgram_socket, secret_message, strlen(secret_message) + 1, 0, 
      (struct sockaddr*) &dest_addr, sizeof dest_addr); 

    return 0; 
} 

再次,发射时你应该从服务器的输出与此类似:

recv()'d 29 bytes of data in buf 
from IP address 127.0.0.1 
+0

这是所有基于TCP ...问题是关于UDP – mark

+0

@mark我已经移植到UDP – 4pie0

How client IP address and port knows to the server ?, 
    Ans: When datagram is recieved(readyRead signal is emited), you can use readDatagram API 
    socketServer.readDatagram(buffer.data(),buffer.size(),&sender,&port); 
    sender = IPaddress of client 
    por = portNumber of client. 

这里是同一本地主机上使用Qt的QUdpSocket提供,1 UDP Sever的解决方案,用多个客户端,测试它正在工作。注释的代码,在必要

有两个控制台应用程序(UDPServer和UDPClient)

How to test 
    1. Run UDPServer, it will listen on port 9999 
    2. Run UDPClient(First instance) 
    3. Run UDPClient(second instance) 

Result: 
    Please check below screenshot 

enter image description here

UDPServer代码

>的main.cpp

int main(int argc, char *argv[]) 
{ 
    QCoreApplication a(argc, argv); 
    UDPServer server; 
    return a.exec(); 
} 

> UDPServer。ħ

#ifndef UDPSERVER_H 
    #define UDPSERVER_H 
    #include <QObject> 
    #include <QUdpSocket> 

    class UDPServer : public QObject 
    { 
     Q_OBJECT 
    public: 
     explicit UDPServer(QObject *parent = 0); 
     void WriteData(const QString&); 

    public slots: 
     void readReady(); 
    private: 
     QUdpSocket socketServer; 

    }; 
    #endif // UDPSERVER_H 

> UDPServer.cpp

#include "UDPServer.h" 
UDPServer::UDPServer(QObject *parent) :QObject(parent),socketServer(this) 
{ 
    qDebug()<<"I am UDP server, listening on 9999"; 
    // Listen to 9999 port server 
    socketServer.bind(QHostAddress::LocalHost,9999); 
    connect(&socketServer,SIGNAL(readyRead()),this,SLOT(readReady())); 

} 

void UDPServer::readReady() 
{ 
    QByteArray buffer; 
    buffer.resize(socketServer.pendingDatagramSize()); 
    QHostAddress sender; 
    quint16 port; 
    socketServer.readDatagram(buffer.data(),buffer.size(),&sender,&port); 
    qDebug()<<"Datagram Recieved From"; 
    qDebug()<<"Client IP" << sender.toString(); 
    qDebug()<<"Client Port Number " << port; 
    qDebug()<<"\n\n"; 

    // Write to the client,need to specify the client port number. 
    QByteArray clientData; 
    clientData.append("data"); 
    socketServer.writeDatagram(clientData, QHostAddress::LocalHost, port); 
} 

UDPClient代码

>的main.cpp

#include <QtCore/QCoreApplication> 
#include "udpclient.h" 

int main(int argc, char *argv[]) 
{ 
    QCoreApplication a(argc, argv); 
    UDPClient client; 
    client.WriteData("What is my IP");  
    return a.exec(); 
} 

> udpclient.h

#ifndef UDPCLIENT_H 
#define UDPCLIENT_H 

#include <QObject> 
#include <QUdpSocket> 

class UDPClient : public QObject 
{ 
    Q_OBJECT 
public: 
    explicit UDPClient(QObject *parent = 0); 
    void WriteData(const QString&); 
public slots: 
    void readReady(); 

private: 
    QUdpSocket clientSocket; 

}; 

#endif // UDPCLIENT_H 

> udpclient.cpp

#include "udpclient.h" 


UDPClient::UDPClient(QObject *parent) :QObject(parent), clientSocket(this) 
{  
    qDebug()<<"I am your client"; 
    connect(&clientSocket,SIGNAL(readyRead()),this,SLOT(readReady())); 
} 

void UDPClient::WriteData(const QString& data) 
{ 
    QByteArray clientData; 
    clientData.append(data);  
    // write to the port, listening by the server. 
    qDebug()<<"Writing datagram to 9999 port"; 
    clientSocket.writeDatagram(clientData, QHostAddress::LocalHost, 9999); 

} 

void UDPClient::readReady() 
{ 
    // got response from server, so clientSoclet port number can get. 
    qDebug()<< "Reacieved response from server through my port(Client port No):" << clientSocket.localPort(); 

    QByteArray buffer;  
    buffer.resize(clientSocket.pendingDatagramSize());   

    QHostAddress sender;  
    quint16 port; 
    clientSocket.readDatagram(buffer.data(),buffer.size(),&sender,&port);  
    // To read server IP 
    qDebug()<< "Server IP Responded" << sender.toString(); 
    qDebug()<< "Server Port Number" << port;  
} 
+0

@Sahil Manchanda,我花了几个小时找到解决方案。请检查答案 – Ashif

+0

是否仅仅因为OP提到qt而使用qt框架,或者是否存在这种方法与使用syscalls socket(),bind()创建套接字的标准方法相比的优势? – 4pie0

+0

@ restart.localhost.localdomain:提到OP并且标记已经用Qt更新:),主要由Qt框架支持的可移植性是很大的优势,系统调用可以利用轻量级进程的优势是否正确?你可以建议我如何运行你的源代码(答案)在Windows环境,cygwin是合适的解决方案吗? – Ashif