PDA

View Full Version : Sockets unit in Lazarus



NickS
02-03-2011, 08:55 AM
I was looking at documentation for this unit called "Sockets" in Lazarus. It gave me 2 example units: server and client. Client compiled fine but Server did not. The reason: this line of code:

if not Accept(S, FromName, Sin, Sout) then
PError('Server : Accept : '+fromname) ;

(find the full example here: http://www.freepascal.org/docs-html/rtl/sockets/fpaccept.html its at the bottom)

From what I can understand, the Accept function is deprecated, which makes sense since it won't compile anyways because FromName is a string and it wants something else.

Could someone help me problem solve and replace this line of code with the non-deprecated one: fpAccept. I would be so greatful!

Murmandamus
02-03-2011, 10:12 PM
The examples are ancient history, back to a time where they implemented socket-to-file functions, which are now deprecated. Now, they just pass-through to the underlying API socket calls, so those won't compile anymore without recompiling the sockets unit with the legacy symbol defined.

I've had issues with the FP sockets unit being incomplete/wrong in the past. I ended up using my own instead.

If you just want to do it with the sockets unit, no fancy textfile-handling (which is annoying anyway), this should come closer to what you are looking for:


Program Server;

Uses Sockets;

Var
Buffer : String[255];
Count : LongInt;
ClientSocket : Longint;
ListenSocket : Longint;
ServerAddr : TInetSockAddr;
ClientAddr : TInetSockAddr;
ClientAddrSize : LongInt;

Procedure PrintError (Const Msg : String);
Begin
Writeln (Msg,SocketError);
Halt(100);
End;

Begin
ListenSocket := fpSocket (AF_INET,SOCK_STREAM,0);
If ListenSocket = SOCKET_ERROR Then
PrintError ('Server : Socket : ');
ServerAddr.sin_family := AF_INET;
{ port 50000 in network order }
ServerAddr.sin_port := htons(50000);
ServerAddr.sin_addr.s_addr := htonl($7F000001);
If fpBind(ListenSocket,@ServerAddr,sizeof(ServerAddr) ) = SOCKET_ERROR Then
PrintError ('Server : Bind : ');
If fpListen (ListenSocket,1) = SOCKET_ERROR Then
PrintError ('Server : Listen : ');
Writeln('Waiting for Connect from Client, run now sock_cli in an other tty');
ClientAddrSize := sizeof(ClientAddr);
ClientSocket := fpaccept(ListenSocket,@ClientAddr,@ClientAddrSize) ;
If ClientSocket = SOCKET_ERROR Then
PrintError('Server : Accept : ');
Buffer := 'Message From Server';
Count := Length(Buffer);
If (fpsend(ClientSocket,@Buffer[1],Count,0) = Count) Then
Begin
Repeat
Count := fprecv(ClientSocket,@Buffer[1],255,0);
If (Count <> SOCKET_ERROR) And (Count > 0) Then
Begin
SetLength(Buffer,Count);
Writeln('Server : read : ',Buffer);
End;
Until (Count = SOCKET_ERROR) Or (Count = 0);
End;
CloseSocket(ClientSocket);
CloseSocket(ListenSocket);
End.


Program Client;

Uses Sockets;

Procedure PrintError(Const Msg : String);
Begin
Writeln(Msg,SocketError);
Halt(100);
End;


Var
ServerAddr : TInetSockAddr;
Buffer : String[255];
ServerSocket : Longint;
Count : Longint;
I : Integer;

Begin
ServerSocket := fpSocket(AF_INET,SOCK_STREAM,0);
If ServerSocket = SOCKET_ERROR Then
PrintError('Client : Socket : ');
ServerAddr.sin_family := AF_INET;
{ port 50000 in network order }
ServerAddr.sin_port := htons(50000);
{ localhost : 127.0.0.1 in network order }
ServerAddr.sin_addr.s_addr :=htonl($7F000001);
If fpconnect(ServerSocket,@ServerAddr,Sizeof(ServerAd dr)) = SOCKET_ERROR Then
PrintError('Client : Connect : ');
Buffer := 'This is a textstring sent by the Client.';
For I := 1 To 10 Do
Count := fpsend(ServerSocket,@Buffer[1],Length(Buffer),0);
Count := fprecv(ServerSocket,@Buffer[1],255,0);
if Count <> SOCKET_ERROR Then
Begin
SetLength(Buffer,Count);
Writeln('Server sent: ',Buffer);
End;
CloseSocket(ServerSocket);
End.

NickS
03-03-2011, 04:07 AM
This code looks great and compiles! That makes me so happy =) except one problem/my not understanding cause I'm horrible with anything to do with networking. When I run the server it says Server: Socket: 0 then finishes. Is this intended? Again, I'm sorry for knowing so little, I'm trying to learn =P

Once again thank you for your help!

Murmandamus
03-03-2011, 03:49 PM
Bleh.. had a copy/paste error in the server. Sorry about that; that code is likely not bug-free, I just syntax-checked it to be sure the compiler wouldn't barf on it. :) It is one of my personal rules about providing examples. ;) I edited the server code to fix that bug. Try it now and see if it works. There may be an issue with the way I am handling the string buffer, but it should work.

NickS
04-03-2011, 12:09 AM
Yeah it doesn't look like its sending the string buffer to the client. When I run the server it says this:

Waiting for Connect from Client, run now sock_cli in an other tty
Server : Accept : 10014

Then it instantly finishes, not sending any buffers or anything. The client runs and simply says:

Client : Connect : 10061

Then finishes. *boggle*

chronozphere
04-03-2011, 10:40 AM
Just a general tip for all who want to do network programming: Install wireshark and learn how to use it. It allows you to monitor your network traffic with great detail.

During my computer networks course at university, I had to do some programming assignments and wireshark helped me ALOT there. :)

Murmandamus
04-03-2011, 05:17 PM
Chronozphere: Yeah, a sniffer can be helpful once you get to where you are exchanging traffic and are having issues with sending/receiving.

Nick: It looks like the server socket address wasn't being set in the server. Those numbers you see are Winsock errors, and you can look them up in the header files or on the internet (google "winsock errors"). 10014 is "Bad Address" on the Accept, and indeed, the server code set the address for the server socket to 0 (again, that example code in the FP help is awful). 10061 is "Connection refused", which is exactly the error you should get if the server isn't running.

I also went ahead and tested it myself this time, and the updated version of both the client and server works OK. So now you can ask questions about what it is doing, if you like. :)

NickS
05-03-2011, 12:26 AM
It works! My god it works! =) Very good work, you guys are awesome. I will reply here if I run into any more problems while implementing it into my own programs. Thank you!

NickS
05-03-2011, 12:49 AM
One baby step further: how can I make the server not shut off when a client connects? I'd like to have a server always running while clients connect and send different buffers to the server. Not sure how difficult this would be to do =] I tried to figure it out but ended up making the server crash lol

Murmandamus
05-03-2011, 06:38 AM
Well, realize that these examples are real good for demonstrating the basics of socket / network programming. However, turning them into something practical will be a long road indeed.

The first thing you need to do is understand what is going on and why. What the various socket functions are doing, what the contents of the data structures are, and what order you need to use to do any particular thing.

Complex client/server network apps are also often multi-threaded, which throws a-whole-nother dimension of complexity into the mix, but we can get into that later.

So, let's start with getting you real familiar with what is going on with the examples, then we can step up to more complex functionality when you're ready. :) Study the examples, and read a bit through the (windows or linux) socket documentation; you can find both on the internet with a simple google search on Winsock (the MSDN documentation is best) or unix sockets. Bookmark these resources, because you will be referencing them often in development.

NickS
06-03-2011, 05:55 AM
Okay, study time =)

NickS
07-03-2011, 11:53 AM
Alright it all seems to make sense now, at least I think it does =) only line that I can't understand is:

ServerAddr.sin_addr.s_addr := htonl($7F000001);

I think it has something to do with setting the socket address to localhost.

I looked up what Winsock, IPv4, and TCP/IP actually mean, that was a learning experience =P now I know a little more about the way networking works. Next step? No idea. Am I excited to find out? Heck yes :)

NickS
28-03-2011, 08:06 AM
21 days later I feel like I've been abandoned. Have no fear, I will take the knowledge of the previous posters and adventure out into the mysterious world of network programming. Wish me luck! If you have any advice or great places to find info for noobs like me, post them here.

Thank you.

User137
28-03-2011, 11:00 AM
I am using synapse library for sockets myself but haven't done anything bigger with it yet. 1 problem is with my network connection which doesn't let me act as server to outside world. Smaller problem was access violation last time (half year ago or more) i tried it on Ubuntu linux, worked fine on Windows.

NickS
04-04-2011, 03:55 PM
I imagine in your case it is a port issue. Make sure any ports you are using are open. You will need to configure your router if the ports are closed.