6

I have a simple server written in c# listening on some port. I have an application in c++ and I need the application to send some information to the server. This information is a struct containing 5 integers. I was thinking that I can send it also as a string: something like: "ID=3, anotherInt=5...". Is it a good idea? If not, how should I do that?

How to make it work? What is your advice?

Thank you.

DaveDum
  • 63
  • 4
  • You may want to look into sending the data in XML. That avoids the byte-order issues of binary and makes it easier to accomodate changes to the schema in the future. – HABO Jan 06 '13 at 18:00
  • I was also thinking about sending it in XML but I couldn't find any tutorial how to do that and I have no experience with XML in c++. – DaveDum Jan 06 '13 at 18:05
  • 1
    See here for XML tutorial [link](http://www.w3schools.com/xml/default.asp) on the C side, there is nothing special to do. Just format your strings into a valid set of XML elements. on the C# side, see [link](http://stackoverflow.com/questions/5582155/c-sharp-create-xml-from-byte-array). There are already built-in classes in .net to easily parse the XML. – OldProgrammer Jan 06 '13 at 18:18
  • 1
    Thank you. Creating an XML itself shouldn't be so hard, I was referring more to sending this xml through network. This is what I don't know how to do. – DaveDum Jan 06 '13 at 18:20
  • As long as sending strings byte order doesn't matter. You're very near to the solution only the last line of your client code sends an pointer instead of the string pointed to. – CubeSchrauber Jan 06 '13 at 18:29
  • Actually sending strings byte order does matter. In what way should I do it if it matters? – DaveDum Jan 06 '13 at 18:40

4 Answers4

3

I think you have a mistake in your code.

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

The prototype for send function is:

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

ln is already a pointer to your char buffer. You are passing in &ln, which is the address of the pointer. Shouldn't it be just "ln"?

OldProgrammer
  • 12,050
  • 4
  • 24
  • 45
  • Thank you, you are right. This helped a bit. Anyway, the string I get in c# is "String t" which is much better than before but still not good enough :( – DaveDum Jan 06 '13 at 18:08
  • You also have a mistake in sizeof(ln). That is the size of the pointer. Assuming a 64-bit pointer, that would result in a value of 8, which is the first 8 bytes of the string. You want the size of the string, so you need to pass in strlen(ln). – OldProgrammer Jan 06 '13 at 18:13
3

You should fix the send() method in client code. sizeof() is wrong way to find the length of string, casts applied on "ln" aren't quite right for what you need there. Check <<this link>> for an example and see how it works for you. BTW, C# code in the server needs some serious re-writing if it were to work predictably. You are using 4096 byte buffer and calls to Read() aren't guaranteed to fetch the entire transmission in one go. You will need a loop just for Read to make sure you are reading everything you need - ofcourse, this needs a clear definition of communication semantics. Happy networking!

Community
  • 1
  • 1
Bobby
  • 251
  • 1
  • 8
  • 1
    Thank you for the answer. Server is so far just for testing if it accepts at least the simple string. I will rewrite it soon. – DaveDum Jan 06 '13 at 18:32
2

First of all, (const char*)&ln is not correct. ln is a char *, so when you take the address of it using & you are getting a char **, which you are then casting to a char *. This is undefined behavior. You'll want to get rid of the & operator. Also you'll probably want to read up on what pointers are and how to use them.

As a rule of thumb, don't cast willy-nilly to make the compiler shut up. The errors are trying to tell you something. However, the sockaddr and sockaddr_in thing is correct; the api is designed that way. If you turn on -Wall in your compiler options, it should give you a warning in the correct place.

ALSO: you want strlen(ln) and not sizeof.

Quick n Dirty Rundown on Pointers

When a type includes * before the variable name, the variable holds a pointer to a value of that type. A pointer is much like a reference in C#, it is a value holding the location of some data. These are commonly passed into functions when a function wants to look at a piece of data that the caller owns, sometimes because it wants to modify it. A string is represented as a char *, which is a pointer to the first character in the string. The two operators that are related to pointers are & and *. & takes an lvalue and returns a pointer to that value. * takes a pointer and returns the value it points to. In this case, you have a string, as a char *, and the function you're calling wants a char *, so you can pass it in directly without casting or using * or &. However, for the other function you have a struct sockaddr_in and it wants a struct sockaddr *, so you (correctly) use & to get a struct sockaddr_in *, then cast it to a struct sockaddr *. This is called "type punning," and is an unpleasant reality of the API. Google will give you a better description of type punning than I can.

Dan
  • 12,409
  • 3
  • 50
  • 87
  • You are right, I'm still a bit lost with pointers. Anyway, how I wrote above, this helped but I still don't get the whole string. – DaveDum Jan 06 '13 at 18:09
0
connect(client_socket, (struct sockaddr *)&clientService, sizeof(clientService));

this is ok, but this line should read:

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

where the conversion (const char*) can be omitted. In your code the value of pointer ln is sent (correctly) but you most likely want to send the string it's pointing to in it's entire length.

Concerning the messages to be send: Converting integers to ascii is not a bad idea. You also may have a look at JSON or Googles protobuf format. Formatters or Parsers can easily be written from scratch.

CubeSchrauber
  • 1,199
  • 8
  • 9