通过网络实现C++和C#应用程序之间的通信

6
我有一个简单的C#服务器在某个端口上监听。我有一个C++应用程序,需要向服务器发送一些信息。这些信息是一个包含5个整数的结构体。我在考虑将其作为字符串发送:类似于“ID=3,anotherInt=5……”。这是一个好主意吗?如果不是,我该怎么做?
如何让它工作?您有什么建议?
谢谢。

你可能想考虑使用XML发送数据。这样可以避免二进制的字节顺序问题,并且更容易适应未来模式的更改。 - HABO
我也考虑用XML方式发送,但是我找不到任何关于如何在C++中使用XML的教程,而且我也没有XML方面的经验。 - DaveDum
1
点击此处查看XML教程链接。在C端,没有什么特别的要做。只需将您的字符串格式化为有效的一组XML元素即可。在C#端,请参见链接。.net中已经内置了类来轻松解析XML。 - OldProgrammer
1
谢谢。创建XML本身不应该那么难,我更关心的是如何通过网络发送该XML。这是我不知道如何做的。 - DaveDum
只要发送字符串时字节顺序无关紧要。您距离解决方案非常接近,只有客户端代码的最后一行发送指针而不是指向的字符串。 - CubeSchrauber
实际上,发送字符串时字节顺序确实很重要。如果它很重要,我应该以什么方式做呢? - DaveDum
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”吗?


谢谢,你说得对。这有点帮助。无论如何,在C#中我得到的字符串是“String t”,比以前好多了,但仍然不够好 :( - DaveDum
你在sizeof(ln)中也犯了一个错误。那是指针的大小。假设64位指针,这将导致值为8,即字符串的前8个字节。你需要的是字符串的大小,因此你需要传入strlen(ln)。 - OldProgrammer

3
你需要修复客户端代码中的send()方法。使用sizeof()函数来查找字符串长度是错误的方式,对"ln"应用的强制类型转换不太适合你在那里所需的内容。请参考<<此链接>>中的示例,并查看它如何为您工作。顺便说一句,如果要可预测地工作,服务器中的C#代码需要进行严格的重写。您正在使用4096字节缓冲区,并且不能保证Read()调用一次就能获取整个传输。您需要一个循环来确保您读取了所有需要的内容 - 当然,这需要明确定义通信语义。祝您网络愉快!

1
谢谢你的回答。目前服务器仅用于测试是否接受简单字符串。我很快会重写它。 - DaveDum

2
首先,(const char*)&ln 是不正确的。 ln 是一个 char *,因此当你使用 & 获取它的地址时,你得到的是一个 char **,然后将其转换为 char *。这是未定义的行为。你需要摆脱 & 运算符。此外, 你可能需要了解指针是什么以及如何使用它们。
作为经验法则,不要随意转换类型以使编译器静默。错误试图告诉你一些事情。但是,sockaddrsockaddr_in 的内容是正确的;这个API就是设计成这样的。如果您在编译器选项中打开-Wall,它应该会在正确的位置给你警告。
另外:你需要使用strlen(ln)而不是sizeof
关于指针的快速概述:
当一个类型在变量名之前包含 * 时,该变量保存该类型的值的指针。指针类似于C#中的引用,它是一个持有某些数据位置的值。当函数想要查看调用者拥有的一些数据时,通常会将这些指针传递到函数中,有时是因为它想要修改它。字符串表示为char *,它是指向字符串中第一个字符的指针。与指针相关的两个运算符是&*&接受一个lvalue并返回该值的指针。 * 接受一个指针并返回其指向的值。在这种情况下,你有一个字符串,作为char *,你要调用的函数需要一个char *,所以你可以直接将其传递而不使用转换或*&来处理它。但是,对于其他函数,你有一个struct sockaddr_in,它需要一个struct sockaddr *,因此你(正确地)使用&来获取一个struct sockaddr_in *,然后将其转换为struct sockaddr *。这被称为“类型游戏”,是API的一个不愉快的现实。谷歌会给你比我更好的类型游戏描述。

你说得对,我还有点懵逼关于指针。不管怎样,如上所述,这确实有所帮助,但我仍然没有完全理解整个字符。 - DaveDum

0
connect(client_socket, (struct sockaddr *)&clientService, sizeof(clientService));

这样可以,但是这一行应该改为:

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

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

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


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接