digitalmars.D.learn - Sockets between D and C(++) app
- Alexandre L. (32/32) Apr 01 2014 Hello,
- bearophile (20/30) Apr 01 2014 If you don't need args, then I suggest to not put it as main
- Alexandre L. (12/23) Apr 01 2014 Thanks for your reply. As for cast, I seems not to have any
- Alexandre L. (3/3) Apr 01 2014 My bad; It returns immutable(char)*.
- Russel Winder (16/27) Apr 02 2014 I am not convinced by this argument. The return value (aka exit code) is
- bearophile (10/12) Apr 02 2014 The _real_ signature of main() is flexible, you can use:
- Dicebot (6/32) Apr 02 2014 D main != C main, latter is implemented in D runtime to call the
- Andrej Mitrovic (7/9) Apr 02 2014 Actually, the compiler injects a return statement in D's main.
- "Ola Fosheim =?UTF-8?B?R3LDuHN0YWQi?= (9/11) Apr 02 2014 I believe in C it is:
- FreeSlave (61/61) Apr 02 2014 It's only server. Maybe problem is on client side.
- Alexandre L. (38/39) Apr 03 2014 Yes, it is only a server which needs to answer back the client;
Hello, I lately did a minimal udp socket server-client application with C++, and I've been trying to recreate it with D, after. I'm able to get the client's request (C++ client) without too much trouble (after I figured I needed to get it in ubyte[]). Then I've tried to send the client an answer through send() (then tried sendTo() ) but none of them work. Here's my 'server' code: int main(string[] args) { auto s = new UdpSocket(); auto addr = new InternetAddress("127.0.0.1", 6666); s.setOption(SocketOptionLevel.IP, SocketOption.REUSEADDR, true); s.bind(addr); while (true) { ubyte[2048] recv_buf; int count = s.receiveFrom(recv_buf); char[] test = cast(char[])recv_buf[0..count-1]; // -1 for C string comp. writefln("Received: %s\n", test); char[] rep = "regan\0".dup; s.send(cast(ubyte[])rep); } writeln("End!"); return 0; } Then the client tries to get the string in a std::string, hence why I did input the \0 literal. I'm also fairly new to D, so any guidance is sure welcomed! Alexandre
Apr 01 2014
Alexandre L.: Some comments on your code:Here's my 'server' code: int main(string[] args) {If you don't need args, then I suggest to not put it as main argument. So probably this is better (note no int nor return, in D they are not needed): void main() { ... }int count = s.receiveFrom(recv_buf);It's better to use immutable here, and infer the type (use const/immutable everywhere you don't really need to mutate a variable/argument/field): immutable count = s.receiveFrom(recv_buf);char[] test = cast(char[])recv_buf[0..count-1]; // -1 for C string comp. writefln("Received: %s\n", test); char[] rep = "regan\0".dup; s.send(cast(ubyte[])rep);casts are dangerous, because they silently assume you know what you are doing. As first try I suggest you to remove every cast() from your D program, and replace them with to!() or other functions like toStringz. Sometimes this is not the most efficient thing to do, but it's safer, so it's better when you start to learn D. Bye, bearophile
Apr 01 2014
On Wednesday, 2 April 2014 at 00:34:08 UTC, bearophile wrote:Thanks for your reply. As for cast, I seems not to have any option, because to! doesn't work as I would expect it. It would return me an array of numbers, instead of a string; So I kept the cast here, since I certainly know what it's doing -for now-. I generally use immutables, you caught me, here :-). As of main and return, I was not aware we could just ignore them if we didn't need them. I love explicit programming. However, I'm still stuck with toStringz(). Since it returns an immutable(char[]), I can't find how to pass it to Socket.send(), and I do not seem to be able to cast away the immutable :-s Alexandrechar[] rep = "regan\0".dup; s.send(cast(ubyte[])rep);casts are dangerous, because they silently assume you know what you are doing. As first try I suggest you to remove every cast() from your D program, and replace them with to!() or other functions like toStringz. Sometimes this is not the most efficient thing to do, but it's safer, so it's better when you start to learn D. Bye, bearophile
Apr 01 2014
My bad; It returns immutable(char)*. Still won't work with send(); Am I right to supposed the receiving client must handle a ubyte[] as well (C++) ?
Apr 01 2014
On Wed, 2014-04-02 at 00:34 +0000, bearophile wrote:Alexandre L.:I am not convinced by this argument. The return value (aka exit code) is always present, if you ignore this by having a void main, it will return 0, i.e. main is not a void function even if you claim it is. As for ignoring the parameters, this is making use of the fact that main is the only function where you do not have to present the correct signature. Perhaps this exception should be removed. The real signature of main in C/C++ is, I believe: int main(int, char**, char**) what is the real signature in D? -- Russel. ============================================================================= Dr Russel Winder t: +44 20 7585 2200 voip: sip:russel.winder ekiga.net 41 Buckmaster Road m: +44 7770 465 077 xmpp: russel winder.org.uk London SW11 1EN, UK w: www.russel.org.uk skype: russel_winderint main(string[] args) {If you don't need args, then I suggest to not put it as main argument. So probably this is better (note no int nor return, in D they are not needed): void main() { ... }
Apr 02 2014
Russel Winder:what is the real signature in D?The _real_ signature of main() is flexible, you can use: void main() int main(in string[] args) pure nothrow D allows you to omit the args if you don't need them, returns 0 if you don't it, and it can be pure/nothrow/ safe as desired.Perhaps this exception should be removed.This special cases cause zero bugs and zero problems, so there is no chance to change this, even if we want (and I don't want). Bye, bearophile
Apr 02 2014
On Wednesday, 2 April 2014 at 08:55:23 UTC, Russel Winder wrote:On Wed, 2014-04-02 at 00:34 +0000, bearophile wrote:D main != C main, latter is implemented in D runtime to call the former. 0 will be also returned by latter, not the former. Also exception will result in >0 status code even if return type is void. It effectively just says that you won't manage status code manually and allows runtime to take care of it.Alexandre L.:I am not convinced by this argument. The return value (aka exit code) is always present, if you ignore this by having a void main, it will return 0, i.e. main is not a void function even if you claim it is. As for ignoring the parameters, this is making use of the fact that main is the only function where you do not have to present the correct signature. Perhaps this exception should be removed. The real signature of main in C/C++ is, I believe: int main(int, char**, char**) what is the real signature in D?int main(string[] args) {If you don't need args, then I suggest to not put it as main argument. So probably this is better (note no int nor return, in D they are not needed): void main() { ... }
Apr 02 2014
On 4/2/14, Dicebot <public dicebot.lv> wrote:D main != C main, latter is implemented in D runtime to call the former. 0 will be also returned by latter, not the former.Actually, the compiler injects a return statement in D's main. It generates the actual C main function (unless WinMain/DllMain is provided), which calls another special D runtime init function, which itself calls the D main function (which itself has the injected return statement unless it's already an int return). It's quite complicated, but it's all open-source so you can inspect it.
Apr 02 2014
On Wednesday, 2 April 2014 at 08:55:23 UTC, Russel Winder wrote:The real signature of main in C/C++ is, I believe: int main(int, char**, char**)I believe in C it is: int main(void) int main(int,char**) or implementation defined (e.g. the third env pointer in the main signature from unix) But the actual entry point is system dependent and can be specified as a link option? On linux "_start" or something like that.
Apr 02 2014
It's only server. Maybe problem is on client side. Try this if you are on Linux: //Linux C client #include <sys/socket.h> #include <sys/types.h> #include <netinet/in.h> #include <arpa/inet.h> #include <stddef.h> #include <string.h> #include <stdio.h> int main() { int sock, res; struct sockaddr_in addr; const char* hello; size_t len; sock = socket(AF_INET, SOCK_DGRAM, 0); if (sock < 0) { printf("Can't create socket\n"); return -1; } addr.sin_family = AF_INET; addr.sin_port = htons(5432); addr.sin_addr.s_addr = inet_addr("127.0.0.1"); hello = "Hello from C"; len = strlen(hello); while (1) { res = sendto(sock, hello, len, 0, (struct sockaddr*)&addr, sizeof(addr)); if (res <= 0) { printf("Can't send\n"); return -1; } } close(sock); return 0; } //D server import std.socket; import std.stdio; int main(string[] args) { auto s = new UdpSocket(AddressFamily.INET); auto addr = new InternetAddress("127.0.0.1", 5432); s.setOption(SocketOptionLevel.IP, SocketOption.REUSEADDR, true); s.bind(addr); while (true) { ubyte[2048] recv_buf; int count = s.receiveFrom(recv_buf[]); char[] test = cast(char[])recv_buf; writefln("Received: %s\n", test); } return 0; } Note that you don't need to remove zero-symbol if you don't pass it from client.
Apr 02 2014
On Wednesday, 2 April 2014 at 21:54:58 UTC, FreeSlave wrote:It's only server. Maybe problem is on client side.Yes, it is only a server which needs to answer back the client; And there was the problem: I was not fetching the client's address, and since UDP is an unconnected protocol, I couldn't send it back with just "send". So what I had to do was to create a client address and pass it in receiveFrom(), and then use sendTo(in data, in clientAddr). Once this was fixed, the server was able to answer my client. N.b. auto addr_client = new InternetAddress didn't seem to work, like if InternetAddress wasn't right for the Address parameter. I explicitely needed Address. Here's the code: module main; import std.stdio; import std.socket; import std.string; import std.conv; int main() { auto s = new UdpSocket(); auto addr = new InternetAddress("127.0.0.1", 6666); s.setOption(SocketOptionLevel.IP, SocketOption.REUSEADDR, true); s.bind(addr); Address addr_client = new InternetAddress(6666); while (true) { ubyte[2048] recv_buf; immutable count = s.receiveFrom(recv_buf, addr_client); char[] test = cast(char[])(recv_buf[0..count-1]); // -1 pour compatibilité avec C string... writefln("Received: %s\n", test); auto rep = toStringz("Hello"); s.sendTo(rep[0..6], addr_client); } return 0; } Thanks all for your help, much appreciated! Alexandre
Apr 03 2014