6

我有一个用 c# 编写的简单服务器,监听某个端口。我有一个 C++ 应用程序,我需要应用程序向服务器发送一些信息。此信息是一个包含 5 个整数的结构。我在想我也可以将它作为字符串发送:例如:“ID = 3,anotherInt = 5 ...”。这是个好主意吗?如果没有,我该怎么做?

如何让它发挥作用?你有什么建议?

谢谢你。

4

4 回答 4

3

我认为你的代码有错误。

char *ln = "String to send";
connect(client_socket, (struct sockaddr *)&clientService, sizeof(clientService));  
send(client_socket,(const char*)&ln, sizeof(ln), 0);

发送函数的原型是:

ssize_t send(int socket, const void *message, size_t length, int flags);

ln 已经是指向您的 char 缓冲区的指针。您正在传递 &ln,这是指针的地址。不应该只是“ln”吗?

于 2013-01-06T18:04:34.363 回答
3

您应该修复客户端代码中的 send() 方法。sizeof() 是查找字符串长度的错误方法,应用于“ln”的强制转换并不完全满足您的需要。查看<<此链接>>以获取示例,看看它如何为您工作。顺便说一句,如果服务器中的 C# 代码要以可预测的方式工作,则需要进行一些认真的重写。您正在使用 4096 字节的缓冲区,并且不能保证调用 Read() 可以一次性获取整个传输。您将需要一个仅用于 Read 的循环,以确保您正在阅读所需的所有内容 - 当然,这需要明确定义通信语义。快乐的网络!

于 2013-01-06T18:12:54.047 回答
2

首先,(const char*)&ln是不正确的。ln是 a char *,因此当您使用它获取地址时,&您会得到 a char **,然后将其转换为 a char *。这是未定义的行为。你会想要摆脱&运营商。此外,您可能还想了解指针是什么以及如何使用它们。

根据经验,不要随意强制编译器让编译器闭嘴。这些错误试图告诉你一些事情。但是,sockaddrandsockaddr_in是正确的;api就是这样设计的。如果你打开-Wall你的编译器选项,它应该在正确的地方给你一个警告。

还:你想要strlen(ln)而不是sizeof.

指针上的快速 n 肮脏破败

当类型包含*在变量名之前时,该变量包含一个指向该类型值的指针。指针很像 C# 中的引用,它是一个保存某些数据位置的值。当一个函数想要查看调用者拥有的一段数据时,这些通常被传递到函数中,有时是因为它想要修改它。字符串表示为 a ,它是指向字符串中第一个字符的指针。与指针相关的两个运算符是和。接受一个左值并返回一个指向该值的指针。接受一个指针并返回它指向的值。在这种情况下,您有一个字符串,作为 a ,并且您正在调用的函数需要 achar *&*&*char *char *,因此您可以直接将其传入,而无需强制转换或使用*or &。但是,对于您拥有 astruct sockaddr_in并且它想要 a的另一个功能struct sockaddr *,因此您(正确地)使用&来获取 a struct sockaddr_in *,然后将其强制转换为 a struct sockaddr *。这称为“类型双关语”,是 API 的一个令人不快的现实。谷歌会给你一个比我更好的类型双关语的描述。

于 2013-01-06T18:05:54.910 回答
0
connect(client_socket, (struct sockaddr *)&clientService, sizeof(clientService));

没关系,但是这一行应该是:

send(client_socket,(const char*)ln, strlen(ln), 0);

其中转换(const char*)可以省略。在您的代码中(正确地)发送了指针 ln 的值,但您很可能希望发送它所指向的字符串的整个长度。

关于要发送的消息:将整数转换为 ascii 并不是一个坏主意。您还可以查看 JSON 或Google 的 protobuf格式。格式化程序或解析器可以很容易地从头开始编写。

于 2013-01-06T18:11:45.947 回答