我創建了一個通過本地網路發送廣播訊息的客戶端:
#define SERVER_PORT "7777"
int main(int argc, char** argv)
{
int sockfd;
struct addrinfo hints, *servinfo, *p;
int rv;
int numbytes;
if (argc != 3) {
fprintf(stderr,"usage: client ip message\n");
exit(1);
}
memset(&hints, 0, sizeof hints);
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_DGRAM;
if ((rv = getaddrinfo(argv[1], SERVER_PORT, &hints, &servinfo)) != 0) {
fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv));
return 1;
}
for(p = servinfo; p != NULL; p = p->ai_next)
{
if ((sockfd = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) == -1)
{
perror("talker: socket");
continue;
}
break;
}
int broadcast = 1;
if (setsockopt(sockfd, SOL_SOCKET, SO_BROADCAST, &broadcast, sizeof broadcast) == -1)
{
perror("setsockopt (SO_BROADCAST)");
exit(1);
}
if (p == NULL) {
fprintf(stderr, "talker: failed to bind socket\n");
return 2;
}
std::cout << "type any number to start: ";
int temp = 0;
std::cin >> temp;
while(1)
{
if ((numbytes = sendto(sockfd, argv[2], strlen(argv[2]), 0, p->ai_addr, p->ai_addrlen)) == -1)
{
std::cout << "[ERROR] sendto error: " << errno << std::endl;
continue;
}
std::cout << "[INFO] sended: " << numbytes << " bytes!" << std::endl;
sleep(5);
}
freeaddrinfo(servinfo);
close(sockfd);
return 0;
}
是的,我正在使用 while(1) 回圈而沒有退出的機會(沒關系)。
此客戶端成功發送廣播訊息。但是如何從服務器端處理它們呢?我試著用下一個方法(服務器被寫成一個類。這是主要方法):
virtual void Init() override
{
addrinfo hints;
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_DGRAM;
int iRes = -1;
if((iRes = getaddrinfo(m_sIpAddress.c_str(), std::to_string(m_iPort).c_str(), &hints, &m_pAddr)) != 0)
{
std::cout << "getaddrinfo error: " << gai_strerror(iRes) << std::endl;
exit(-1);
}
std::cout << "getaddrinfo success!" << std::endl;
m_iSocket = socket(AF_INET, SOCK_DGRAM, 0);
if(m_iSocket == -1)
{
std::cout << "socket error: " << errno << std::endl;
exit(-1);
}
std::cout << "socket created!" << std::endl;
if((iRes = bind(m_iSocket, m_pAddr->ai_addr, m_pAddr->ai_addrlen)) == -1)
{
std::cout << "bind error: " << errno << std::endl;
exit(-1);
}
std::cout << "binded successfully!" << std::endl;
}
virtual void Listen() override
{
int iNumOfReadBytes = -1;
std::string msg;
msg.resize(1024);
sockaddr_in clientAddr;
socklen_t addrLen = sizeof(sockaddr);
while(true)
{
if((iNumOfReadBytes = recvfrom(m_iSocket, const_cast<char*>(msg.c_str()), 1024-1, 0, reinterpret_cast<sockaddr*>(&clientAddr), &addrLen)) == -1)
{
std::cout << "recvfrom error: " << errno << std::endl;
continue;
}
char ip[16]; //string for ip
inet_ntop(AF_INET, &(clientAddr.sin_addr), ip, 16);
std::cout << "[";
for (int i = 0; i < 16; i )
{
std::cout << ip[i];
}
std::cout << "]";
std::cout << msg << std::endl;
}
}
Init 方法負責初始化套接字,Listen 方法負責處理廣播訊息。
讓我們想象一下,服務器有 192.168.88.123 ip 地址,而客戶端在 192.168.88.255 ip 上發送廣播訊息。我想,服務器應該從客戶端獲取訊息,但它實際上從未收到它們。
我還嘗試將客戶端配置為向 255.255.255.255 ip 發送訊息。訊息已發送,但服務器未收到訊息。
那么是代碼的錯嗎?或者有IP的東西(如果是這樣,那很奇怪)?
PS 我閱讀了 Beej 的網路指南。有一個廣播示例,但僅來自客戶端。但我對處理來自服務器端的此類訊息很感興趣。
謝謝!
uj5u.com熱心網友回復:
代碼看起來不錯(不過,我建議進行一些調整,例如IPPROTO_UDP在呼叫時指定協議getaddrinfo(),并在服務器端包含AI_PASSIVE標志)。
默認情況下,并非所有網路路由器都允許 UDP 廣播。因此,請檢查您的路由器配置以及作業系統防火墻。使用資料包嗅探器(如 WireShark)來確保資料包實際離開發送方的 NIC 并到達接收方的 NIC,以確保它們在傳輸程序中沒有被阻塞。
此外,請仔細檢查以確保您的客戶端套接字和服務器套接字系結到同一子網,并且客戶端正在發送到該子網的正確廣播 IP。給定 的服務器 IP ,只有子網掩碼為時192.168.88.123,廣播 IP 才會是,您的環境是這種情況嗎?192.168.88.255255.255.255.0
此外,如果您的服務器系結到0.0.0.0(偵聽所有本地 NIC)而不是系結到192.168.88.123(僅偵聽 1 個 NIC),請檢查您是否有同樣的問題。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/485248.html
上一篇:訊息很大,您可能需要考慮較小的訊息。node-ipc和swift(OSX)
下一篇:根據屬性的值修改元素的值
