- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我必须编写一个程序,将文件从 UDP 客户端发送到 UDP 服务器。
我通过这种连接发送数据没有任何问题,但不同的问题是处理我们的协议(protocol)规范。也许有人可以帮助我理解如何正确实现这些步骤:
发送第一个包:数据数组的第一个元素,类型规范的 int
值。
之后文件名大小(不带路径)为无符号短
。
之后文件名(不带路径)为 C 字符串,不带 NULL 终止符。
至少文件长度应该是无符号整数
。
两种大小都应按网络字节顺序发送!
所有这些信息都必须位于一个单个数据报中。所以实际上我只有一个由客户端发送的 unsigned char
数组。
我以为我可以将任何东西一个接一个地分配给这个数组。但不要认为这有效。
发送第二个包:类型规范为 int
作为第一个元素。然后是给定文件的数据(我也将其保存为 unsigned char
数组)。这要容易得多,因为我只拥有可以轻松放入我的 unsigned char
数组中的信息。
所以,我认为,必须有一种方法来构建一个通用方法或类似的方法,它返回一个数据报,这样我就可以填写我想要在此数据报中包含的所有数据类型,并准备好发送我的数据报, 你知道?
如果有人知道我如何以正确的方式“准备”数据报,那就太好了 - 对我来说最重要的是:
我的数据报数组应该具有哪种类型?要使用 sendTo()
发送它,它需要是一个 unsigned char
数组,对吗?
最诚挚的问候,非常感谢!
最佳答案
您可以使用结构来映射您的信息,例如:
struct Packet {
unsigned short filnemanesize;
char [MAX_LEN] filename;
unsigned int filesize;
//etc.
}
您可以直接通过套接字发送该结构
send(mySocket, (void*) myStruct, sizeof(myStuct), 0);
但是编译器使用不同的成员包装,因此服务器会看到不同的数据。 (对于完全相同的平台/编译器来说是安全的)。
常见的做法是将结构序列化为 char 数组,这是一个完整的示例:
#include <stdint.h>
#include <iostream>
#include <WinSock2.h>
#pragma comment(lib, "Ws2_32.lib")
using namespace std;
#define MAX_FILENAME_SIZE 10
typedef struct {
int32_t type;
uint16_t fileNameSize;
uint32_t extraPadding; //just some manual padding (example)
char fileName [MAX_FILENAME_SIZE];
uint32_t fileSize;
} Packet;
const size_t PACKET_RAW_SIZE = sizeof(int32_t) + sizeof(uint16_t) + (MAX_FILENAME_SIZE * sizeof(char)) + sizeof(uint32_t);
size_t serialize(unsigned char * const dst, const Packet * src) {
/* Protocoll Specification:
[Type:4Byte][fileNameSize:2Byte][fileName:nByte][fileSize:4Byte]
*/
uint16_t offset = 0;
//type
memcpy(dst + offset, &src->type, sizeof(src->type));
offset += sizeof(src->type);
//fileNameSize
memcpy(dst + offset, &src->fileNameSize, sizeof(src->fileNameSize));
offset += sizeof(src->fileNameSize);
//fileName
memcpy(dst + offset, &src->fileName, ntohs(src->fileNameSize));
offset += ntohs(src->fileNameSize);
//fileSize
memcpy(dst + offset, &src->fileSize, sizeof(src->fileSize));
offset += sizeof(src->fileSize);
return offset;
}
int main(int argc, _TCHAR* argv[])
{
unsigned char buffer[PACKET_RAW_SIZE];
for (int i = 0; i < PACKET_RAW_SIZE; buffer[i++] = 0); //nice visual effect, not nessasarry
Packet myPacket;
myPacket.type = htonl(0xAFFEAFFE);
myPacket.fileNameSize = htons(4); //convert 4 to network byte order as required
myPacket.fileSize = htonl(42);
myPacket.fileName[0] = 'T';
myPacket.fileName[1] = 'E';
myPacket.fileName[2] = 'S';
myPacket.fileName[3] = 'T';
myPacket.extraPadding = 0xFFFFFFFF; // better visual effect
cout << "struct Packet size: " << sizeof(Packet) << endl;
cout << "PACKET_RAW_SIZE: " << PACKET_RAW_SIZE << endl;
size_t bufferSize = serialize(&buffer[0], &myPacket);
cout << "myPacket: " << endl;
for (int i = 0; i < sizeof(myPacket); i++) {
unsigned char * ptr = (unsigned char *) &myPacket;
cout << std::showbase << std::hex << "Offset: " << i * sizeof(unsigned char) << "\t Value: " << (uint16_t)*(ptr + i) << "\t" << *(ptr + i) << endl;
}
cout << endl;
cout << "buffer: " << endl;
for (int i = 0; i < bufferSize; i++) {
cout << std::showbase << std::hex << "Offset: " << i * sizeof(unsigned char) << "\t Value: " << (uint16_t)buffer[i] << "\t" << buffer[i] << endl;
}
cout << endl;
return 0;
}
/*
Program-Output:
struct Packet size : 28
PACKET_RAW_SIZE : 20
myPacket :
Offset : 0 Value : 0xaf »
Offset : 0x1 Value : 0xfe ■
Offset : 0x2 Value : 0xaf »
Offset : 0x3 Value : 0xfe ■
Offset : 0x4 Value : 0
Offset : 0x5 Value : 0x4 ♦
Offset : 0x6 Value : 0x9a Ü
Offset : 0x7 Value : 0xf ☼
Offset : 0x8 Value : 0xff
Offset : 0x9 Value : 0xff
Offset : 0xa Value : 0xff
Offset : 0xb Value : 0xff
Offset : 0xc Value : 0x54 T
Offset : 0xd Value : 0x45 E
Offset : 0xe Value : 0x53 S
Offset : 0xf Value : 0x54 T
Offset : 0x10 Value : 0x52 R
Offset : 0x11 Value : 0x17 ↨
Offset : 0x12 Value : 0x9f ƒ
Offset : 0x13 Value : 0xf ☼
Offset : 0x14 Value : 0x1 ☺
Offset : 0x15 Value : 0
Offset : 0x16 Value : 0
Offset : 0x17 Value : 0
Offset : 0x18 Value : 0
Offset : 0x19 Value : 0
Offset : 0x1a Value : 0
Offset : 0x1b Value : 0x2a *
buffer :
Offset : 0 Value : 0xaf » | <= type
Offset : 0x1 Value : 0xfe ■ |
Offset : 0x2 Value : 0xaf » |
Offset : 0x3 Value : 0xfe ■ |
Offset : 0x4 Value : 0 | <= fileNameSize
Offset : 0x5 Value : 0x4 ♦ | (network byte order)
Offset : 0x6 Value : 0x54 T | <= fileName
Offset : 0x7 Value : 0x45 E |
Offset : 0x8 Value : 0x53 S |
Offset : 0x9 Value : 0x54 T |
Offset : 0xa Value : 0 | <= fileSize
Offset : 0xb Value : 0 | (network byte order)
Offset : 0xc Value : 0 |
Offset : 0xd Value : 0x2a |
*/
可以看到,缓冲区只包含所需的数据。并且映射是按照规范中的要求进行的。所有手动和编译器填充都不在缓冲区内。htons/htonl 用于字节顺序转换。
更好的是某种文本序列化,例如 xml 或 json(恕我直言)
关于c - 如何准备 UDP 数据报发送到服务器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30501561/
我有一个twisted从这里代理:Python Twisted proxy - how to intercept packets . 它打印 HTTP 数据,我还想拦截并检查原始 IP 数据报。如何h
如果我在从客户端到服务器的 udp 套接字(在我的例子中是 QUdpSocket)上连续写入 2 次,我是否可能只收到一个数据报,其中包含我从客户端写入的两个数据?或者我确定我总是会得到 2 个单独的
我正在尝试使用原始套接字在 ruby 中编写自己的 UDP 实现,以用于教育目的。 这是我到目前为止所拥有的: require 'socket' addr = Socket.pack_sockad
我有一个非常基本的问题。想象一下,有一个简单的 udp 客户端,它正在监听传入的数据报。这些数据报只是字节[],但它们可能包含复杂的信息,如字符串、整数等。 是否有任何优雅的方法来解码数据报,例如使用
我必须开发一个分布式系统,该系统包括通过 TCP 套接字与来自其 IP 地址的某人进行聊天 session ,该系统连接到一个服务器,该服务器列出了过去 3 分钟连接到它的所有 ip。除了这个主要功能
使用Java编写基于UDP的客户端/服务器。 当服务器不断从套接字获取数据包时: socket.receive(packet); 即使客户端发送多个数据包,例如数据包 1、2、3 和 4,客户端也只能
您好,我想制作一个与“SendIP 发送任意 IP 数据包的命令行工具”类似的程序 我有一个程序可以发送“IPv4 + UDP”。我尝试通过 Wireshark 验证我的程序,但没有收到任何消息,我不
我正在尝试设计一个系统,其中有发送方和接收方,双方都可以发送和接收数据包。我为每个发送方和接收方使用 2 个数据报 channel ,并在每一侧使用 2 个线程来处理该问题。 从发送者向接收者发送数据
我的问题:使用 net.Read... 方法仅复制给定字节数组或 slice 大小的字节数。我当然不想每次都分配最大 64 kB 的 UDP 数据报。 是否有go方法来确定数据报的大小(在数据报头中)
考虑通过套接字发送的 100 个字节。使用 TCP 套接字,如果我调用 recv()长度为 50,我得到前 50 个字节,如果我再次调用它,我得到第二个 50 个字节。使用 UDP 套接字,如果我调用
有谁知道 Tibco rvd 数据报的可用 Javadoc(特别是类“com.tibco.tibrv.TibrvMsg”)?反编译类以获得签名并不难,但这并不能说明预期的最佳用法等。 我所需要的只是用
通过无连接数据报 Unix 套接字发送时出现 ECONNREFUSED 的可能原因是什么? 也欢迎任何有关如何调试此问题的建议,因为此问题是可重现的。 无论是否使用 sendto() 或 sendms
在为 Android 编写一个简单的 UDP 广播应用程序时,我遇到了一个奇怪的问题。 基本上,我的应用程序想要将数据流广播到本地网络上的设备。每个 UDP 数据包都有一个按顺序递增的数字,以便我知道
简单地说,我能够从连接的套接字接收数据,直到它启动后大约 10 秒。解决此问题的解决方案是,将数据发送到“客户端”(ARDrone)以保持数据流继续运行,否则它将停止向手机发送数据。但是,出于某种原因
这个问题在这里已经有了答案: How do I get amount of queued data for UDP socket? (2 个回答) 3年前关闭。 哪一个ioctl的 FIONREAD返
我正在向这个 Haskell 服务器发送简单的 UDP 数据包。对于数据包的来源,我使用“aspell -l en dump master”生成的纯文本文件。但是,任何超过 120,000 条消息的列
服务器: $address = '127.0.0.1'; $port = 46123; if (($sock = socket_create(AF_INET, SOCK_STREAM, SOL_
我有一个宽带雷达,我想打开。要打开它,我必须发送两个寄存器,如下所示: int reg0[3] = {0x00, 0xC1, 0x01}; int reg1[3] = {0x
我正在尝试使用 udp 套接字发送一些数据,并通过 Windows 环回适配器在同一个套接字上接收它们。在我的网络属性中,我将环回适配器设置为具有以下 ip 192.168.1.1 recvfrom
这个问题在这里已经有了答案: How does Skype work without port forwarding? (4 个答案) 关闭 9 年前。 我是网络新手...我有一个(愚蠢?:))关于
我是一名优秀的程序员,十分优秀!