TCP/IP UDP廣播無法發(fā)送或者接收數(shù)據(jù)
在看《TCP/IP 網(wǎng)絡(luò)編程》這本書的時候,看到廣播那一節(jié),跟著書上寫代碼,怎么寫都不行,廣播就是沒法發(fā)送/接收,發(fā)送端一直在發(fā)送數(shù)據(jù),接收端就是沒有反應(yīng)。
對了好幾遍源碼,沒有問題。實在是愁人。
最后查了很多資料,確定是網(wǎng)卡的問題。
現(xiàn)在的計算機(jī)都是多網(wǎng)卡,至少是有線+無線網(wǎng)卡,如果安裝了虛擬機(jī)的話,還會有虛擬網(wǎng)卡。
廣播地址無法區(qū)分網(wǎng)卡,只能按照默認(rèn)網(wǎng)卡優(yōu)先級發(fā)送,這就導(dǎo)致我們的數(shù)據(jù)沒有走那個我們需要的網(wǎng)卡發(fā)送出去。進(jìn)而導(dǎo)致收不到數(shù)據(jù)。
解決辦法
- 禁用一些網(wǎng)卡,將用不到的網(wǎng)卡全部禁用掉
- 在代碼里添加綁定IP地址的邏輯,綁定到具體的網(wǎng)卡IP
我是用的是第2種方式,比較方便靈活。
發(fā)送端Linux源碼:
#include <arpa/inet.h>
#include <asm-generic/socket.h>
#include <cstdio>
#include <cstring>
#include <fstream>
#include <iostream>
#include <iterator>
#include <linux/in.h>
#include <sys/endian.h>
#include <sys/socket.h>
#include <unistd.h>
#ifndef FILEPATH
#define FILEPATH "../news.txt"
#endif
constexpr int BUF_SIZE = 30;
int main(int argc, char* argv[])
{
if (argc != 4) {
std::cout << "Usage: " << argv[0] << "<Self IP> <Boardcast IP> <PORT>" << std::endl;
return 0;
}
int send_socket = socket(PF_INET, SOCK_DGRAM, 0);
// 綁定到具體的網(wǎng)卡IP
sockaddr_in self_adr;
std::memset(&self_adr, 0, sizeof(self_adr));
self_adr.sin_family = AF_INET;
self_adr.sin_addr.s_addr = inet_addr(argv[1]);
self_adr.sin_port = 0; // 隨機(jī)分配一個端口
int res = bind(send_socket, (sockaddr*)&self_adr, sizeof(self_adr));
if (res == -1) {
std::cout << "bind error";
}
sockaddr_in broad_adr;
std::memset(&broad_adr, 0, sizeof(broad_adr));
broad_adr.sin_family = AF_INET;
broad_adr.sin_addr.s_addr = inet_addr(argv[2]);
broad_adr.sin_port = htons(std::atoi(argv[3]));
int so_brd = 1;
int rtn = setsockopt(send_socket, SOL_SOCKET, SO_BROADCAST, &so_brd, sizeof(so_brd));
if (rtn == -1) {
std::cout << "setsockopt error" << std::endl;
return 0;
}
std::ifstream fi { FILEPATH };
while (!fi.eof()) {
std::string msg;
fi >> msg;
int s = sendto(send_socket, msg.c_str(), msg.size(), 0, (sockaddr*)&broad_adr, sizeof(broad_adr));
std::cout << s << ":" << msg << std::endl;
sleep(2);
}
close(send_socket);
return 0;
}
接收端Linux源碼:文章來源:http://www.zghlxwxcb.cn/news/detail-763660.html
#include <arpa/inet.h>
#include <cstring>
#include <iostream>
#include <linux/in.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <unistd.h>
constexpr int BUF_SIZE = 30;
int main(int argc, char* argv[])
{
if (argc != 2) {
std::cout << "Usage: " << argv[0] << " <PORT>" << std::endl;
return 0;
}
int recv_sock = socket(PF_INET, SOCK_DGRAM, 0);
sockaddr_in adr;
std::memset(&adr, 0, sizeof(adr));
adr.sin_family = AF_INET;
adr.sin_addr.s_addr = htonl(INADDR_ANY);
int port = std::atoi(argv[1]);
adr.sin_port = htons(port);
std::cout << "PORT: " << port << std::endl;
int rtn = bind(recv_sock, (sockaddr*)&adr, sizeof(adr));
if (rtn == -1) {
std::cout << "bind error" << std::endl;
return 0;
}
char buf[BUF_SIZE] = { 0 };
while (true) {
sockaddr_in src_adr;
socklen_t sl = 0;
int l = recvfrom(recv_sock, buf, BUF_SIZE - 1, 0, (sockaddr*)&src_adr, &sl);
std::string srcIp = inet_ntoa(src_adr.sin_addr);
std::cout << srcIp << " - ";
if (l < 0) {
break;
}
buf[l] = 0;
std::cout << buf;
}
close(recv_sock);
return 0;
}
接收端Win源碼:文章來源地址http://www.zghlxwxcb.cn/news/detail-763660.html
#include <WS2tcpip.h>
#include <WinSock2.h>
#include <cstdlib>
#include <cstring>
#include <iostream>
constexpr int BUF_SIZE = 30;
int main(int argc, char* argv[])
{
if (argc != 2) {
std::cout << "Usage: " << argv[0] << " <PORT>" << std::endl;
return 0;
}
WSADATA wsaData;
if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) {
std::cout << "WSA error" << std::endl;
return 0;
}
SOCKET recvSock = socket(PF_INET, SOCK_DGRAM, 0);
SOCKADDR_IN adr;
std::memset(&adr, 0, sizeof(adr));
adr.sin_family = AF_INET;
adr.sin_addr.s_addr = htonl(INADDR_ANY);
int port = std::atoi(argv[1]);
adr.sin_port = htons(port);
int rtn = bind(recvSock, (SOCKADDR*)&adr, sizeof(adr));
if (rtn == SOCKET_ERROR) {
std::cout << "bind error" << std::endl;
return 0;
}
std::cout << "服務(wù)已啟動:" << port << std::endl;
char buf[BUF_SIZE] = { 0 };
while (true) {
int strLen = recvfrom(recvSock, buf, BUF_SIZE - 1, 0, nullptr, 0);
if (strLen < 0) {
break;
}
buf[strLen] = 0;
std::cout << buf << std::endl;
}
closesocket(recvSock);
WSACleanup();
return 0;
}
到了這里,關(guān)于TCP/IP UDP廣播無法發(fā)送或接收的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!