Recent

Author Topic: Is there is Windows Socket  (Read 10275 times)

manjunath

  • New member
  • *
  • Posts: 9
Is there is Windows Socket
« on: January 15, 2017, 04:45:24 pm »
Hi,

Can someone tell me as to what is the problem with the following code ?
This one does not work with the browser.

program trysocket;
uses
   sockets,sysutils,winsock;
var
   serverMessage : String;
   clientMessage : String;
   headerString : String;
   ServerAddr : TInetSockAddr;
   ClientAddr : TInetSockAddr;
   ClientSocket : LongInt;
   ServerSocket : LongInt;
   ClientAddrSize : LongInt;
   count : LongInt;
procedure PrintError(Const Msg :String);
begin
   Writeln(Msg,SocketError);
   Halt(100);
end;   
begin
   ServerSocket := fpSocket(AF_INET,SOCK_STREAM,0);
   if ServerSocket = SOCKET_ERROR then
      PrintError('Server Socket Error : ');
   ServerAddr.sin_family := AF_INET;
   ServerAddr.sin_port := htons(9090);
   if fpBind(ServerSocket,@ServerAddr,SizeOf(ServerAddr)) = SOCKET_ERROR then
      PrintError('Server Bind Error : ');
   if fpListen(ServerSocket,1) = SOCKET_ERROR then
      PrintError('Server Listen Error : ');
   Writeln('Waiting for connection from client');         
      ClientAddrSize := SizeOf(ClientAddr);
      ClientSocket := fpAccept(ServerSocket,@ClientAddr,@ClientAddrSize);   
      if ClientSocket = SOCKET_ERROR then
         PrintError('Client Socket Accept Error : ');

      Writeln('Client Socket Created ',ClientSocket);
      count := fprecv(ClientSocket,@clientMessage,20000,0);
      Writeln(clientMessage);
      if (count <> SOCKET_ERROR) And (count > 0) then
      begin
         serverMessage := 'HTTP/1.0 404 Not Found\n';
         Writeln(ClientSocket,serverMessage,23);
         fpSend(ClientSocket,@serverMessage,23,4);      
      end;   

      CloseSocket(ClientSocket);

end.


Thanks in advance.

rvk

  • Hero Member
  • *****
  • Posts: 6169
Re: Is there is Windows Socket
« Reply #1 on: January 15, 2017, 05:07:26 pm »
Hi and Welcome,

Next time try to put code between code-tags. It's much better readable that way. Also try to mention what errors you're getting and what you expect from the code. Just dumping code and saying it doesn't work isn't a really useful problem-description.

Your problem lies in this line:
Code: Pascal  [Select][+][-]
  1.       count := fprecv(ClientSocket,@clientMessage,20000,0);
Your clientmessage is a String. But a string-type is just a pointer to a memory location where you have characters. But that memory-location isn't yet defined. It normally get's defined when you do clientmessage := 'abc' or SetLength(clientMessage, 2000) or something.

So either declare clientmessage as array[0..32000] of char or do a SetLength(ClientMessage, 32000) before calling this line. (With as much data as you expect to receive.

In your case you're trying to read 20000 chars so this will work:
Code: Pascal  [Select][+][-]
  1. var
  2.   clientmessage: array[0..20000] of char;
  3. ...
  4. count := fprecv(ClientSocket,@clientMessage,20000,0);

« Last Edit: January 15, 2017, 05:17:16 pm by rvk »

Thaddy

  • Hero Member
  • *****
  • Posts: 14385
  • Sensorship about opinions does not belong here.
Re: Is there is Windows Socket
« Reply #2 on: January 15, 2017, 05:27:45 pm »
array[0..19999] of char? Strictly speaking it is always BYTE not CHAR.
Object Pascal programmers should get rid of their "component fetish" especially with the non-visuals.

rvk

  • Hero Member
  • *****
  • Posts: 6169
Re: Is there is Windows Socket
« Reply #3 on: January 15, 2017, 05:32:11 pm »
array[0..19999] of char? Strictly speaking it is always BYTE not CHAR.
You're right about the 19999.

But if you make it array of byte you can't treat it like a string.
With array of char you can do writeln(clientmessage); With array of byte you can't and need to convert it.

manjunath

  • New member
  • *
  • Posts: 9
Re: Is there is Windows Socket
« Reply #4 on: January 15, 2017, 05:40:27 pm »
Thanks a lot.
Will try this.
My other doubt is whether I should use Windows socket or not. I am trying this on Windows 10 system.



Regards

Thaddy

  • Hero Member
  • *****
  • Posts: 14385
  • Sensorship about opinions does not belong here.
Re: Is there is Windows Socket
« Reply #5 on: January 15, 2017, 06:16:10 pm »
Windows sockets are simply the Berkeley socket implementation for Windows. It is basically the same on most if not all other platforms as well.
All what is otherwise provided are higher level wrappers and/or additions.

@rvk:
The protocol streams should be treated as bytes. because the protocol says stream then store (including store to a screen, file, memory, whatever).
Conversions for display are costly and should be done where appropriate. Therefor only treat the buffers as string when it is clear it is a string.
Which is not often the case..... Even html pages are byte streamed, not string streamed.
Object Pascal programmers should get rid of their "component fetish" especially with the non-visuals.

manjunath

  • New member
  • *
  • Posts: 9
Re: Is there is Windows Socket
« Reply #6 on: January 15, 2017, 06:34:36 pm »
Thanks a lot for the inputs.
Coming from the java stream, I am adjusting to the new paradigm. All your inputs would be of great help.
Appreciate you guys.

Remy Lebeau

  • Hero Member
  • *****
  • Posts: 1314
    • Lebeau Software
Re: Is there is Windows Socket
« Reply #7 on: January 15, 2017, 08:02:00 pm »
In addition to what others said, recv() can return either -1 on error, 0 on graceful disconnect, and > 0 on success, so checking for >0 by itself is sufficient in your example.

But more importantly, you are sending an HTTP response (are you trying to implement an HTTP server?), but your response is incomplete. HTTP uses CRLF line breaks, and an HTTP message separates its headers and body using 2 line breaks, but you are only sending one.  And you should include a "Content-Length: 0" header so the client knows you are not sending any body data, and also include a "Connection: close" header so the client knows you are about to close the socket connection.

If you really want to implement an HTTP server, consider using a pre-existing solution, such as the TIdHTTPServer component in Indy.
« Last Edit: January 15, 2017, 08:06:19 pm by Remy Lebeau »
Remy Lebeau
Lebeau Software - Owner, Developer
Internet Direct (Indy) - Admin, Developer (Support forum)

manjunath

  • New member
  • *
  • Posts: 9
Re: Is there is Windows Socket
« Reply #8 on: January 15, 2017, 08:08:16 pm »
Hi,

I tried the following code. But it shows me a blank page. Can you please let me know why ?

Code: Pascal  [Select][+][-]
  1. program trysocket;
  2. uses
  3.         sockets,sysutils,winsock;
  4. var
  5.         serverMessage : String;
  6.         clientMessage : array[0..19999] of char;
  7.         headerString : String;
  8.         ServerAddr : TInetSockAddr;
  9.         ClientAddr : TInetSockAddr;
  10.         ClientSocket : LongInt;
  11.         ServerSocket : LongInt;
  12.         ClientAddrSize : LongInt;
  13.         count : LongInt;
  14.         msglen : integer;
  15. procedure PrintError(Const Msg :String);
  16. begin
  17.         Writeln(Msg,SocketError);
  18.         Halt(100);
  19. end;   
  20. begin
  21.         ServerSocket := fpSocket(AF_INET,SOCK_STREAM,0);
  22.         if ServerSocket = SOCKET_ERROR then
  23.                 PrintError('Server Socket Error : ');
  24.         ServerAddr.sin_family := AF_INET;
  25.         ServerAddr.sin_port := htons(9090);
  26.         if fpBind(ServerSocket,@ServerAddr,SizeOf(ServerAddr)) = SOCKET_ERROR then
  27.                 PrintError('Server Bind Error : ');
  28.         if fpListen(ServerSocket,1) = SOCKET_ERROR then
  29.                 PrintError('Server Listen Error : ');
  30.         Writeln('Waiting for connection from client');                 
  31.                 ClientAddrSize := SizeOf(ClientAddr);
  32.                 ClientSocket := fpAccept(ServerSocket,@ClientAddr,@ClientAddrSize);    
  33.                 if ClientSocket = SOCKET_ERROR then
  34.                         PrintError('Client Socket Accept Error : ');
  35.  
  36.                 Writeln('Client Socket Created ',ClientSocket);
  37.                 count := fprecv(ClientSocket,@clientMessage,20000,0);
  38.                 Writeln(clientMessage);
  39.                 if (count <> SOCKET_ERROR) And (count > 0) then
  40.                 begin
  41.                         serverMessage := 'HTTP/1.1 200 OK' +slinebreak;
  42.                         serverMessage := serverMessage + 'Date: Mon, 27 Jul 2009 12:38:53 GMT' + slinebreak;
  43.                         serverMessage := serverMessage + 'Server: MyServer (Win64)' + slinebreak;
  44.                         serverMessage := serverMessage + 'Last-Modified: Wed 22 Jul 2009 19:15:56 GMT'+slinebreak;
  45.                         serverMessage := serverMessage + 'Content-Length: 71'+slinebreak;
  46.                         serverMessage := serverMessage + 'Content-Type: text/html'+slinebreak;
  47.                         serverMessage := serverMessage + 'Connection: Closed'+slinebreak;
  48.                         serverMessage := serverMessage + '<html><title>Main Page</title><body><h1>Hello World!</h1></body><html>';
  49.                         msglen := Length(serverMessage);
  50.                         Writeln(serverMessage);
  51.                         Writeln(msglen);
  52.                         fpSend(ClientSocket,@serverMessage,msglen,0);          
  53.                 end;   
  54.  
  55.                 CloseSocket(ClientSocket);
  56.  
  57. end.
  58.  
  59.  

molly

  • Hero Member
  • *****
  • Posts: 2330
Re: Is there is Windows Socket
« Reply #9 on: January 15, 2017, 09:30:32 pm »
Have you actually read and understood what Remy Lebeau wrote ?

Quote
but your response is incomplete. HTTP uses CRLF line breaks, and an HTTP message separates its headers and body using 2 line breaks, but you are only sending one.  And you should include a "Content-Length: 0" header so the client knows you are not sending any body data, and also include a "Connection: close" header so the client knows you are about to close the socket connection.

If you fix those mentioned above + not use sLineBreak (platform dependent), use @serverMessage[1] (mode ansistring) and keep the connection alive (you tell the client to close it directly) red: add the actual content length, then things start to work  :)
« Last Edit: January 15, 2017, 09:43:33 pm by molly »

manjunath

  • New member
  • *
  • Posts: 9
Re: Is there is Windows Socket
« Reply #10 on: January 15, 2017, 09:56:29 pm »
Thank you very much. Its working.
CRLF is different than sLineBreak and this caused problem - I have understood this now
1 lines after the header instead of 2 was another problem - I have understood this now
@serverMessage[1] is another problem - I have not understood this.

I have a question on @ServerMessage[1].
Why should it be ServerMessage[1] ?

molly

  • Hero Member
  • *****
  • Posts: 2330
Re: Is there is Windows Socket
« Reply #11 on: January 15, 2017, 10:03:13 pm »
Thank you very much. Its working.
A little jig-saw-puzzle is always nice to attempt yourself first, especially when you succeed  :)

Quote
I have a question on @ServerMessage[1].
Why should it be ServerMessage[1] ?
Pascal strings.

Add the following line somewhere in your code and attempt to compile (read the error message carefully):
Code: [Select]
  ServerMessage[0] := #11;
Quote
Error: Element zero of an ansi/wide- or longstring cannot be accessed, use (set)length instead

The zero index of a string contains the length of a string. For more information on pascal string types see also here.
« Last Edit: January 15, 2017, 10:07:07 pm by molly »

manjunath

  • New member
  • *
  • Posts: 9
Re: Is there is Windows Socket
« Reply #12 on: January 16, 2017, 08:03:14 am »
Thanks a lot for the explanation.
Having come from the Java stream, I assumed that the string in pascal is the same as the String in java.
In pascal it is an array where the length is stored in the 0th index.

Leledumbo

  • Hero Member
  • *****
  • Posts: 8757
  • Programming + Glam Metal + Tae Kwon Do = Me
Re: Is there is Windows Socket
« Reply #13 on: January 17, 2017, 01:31:25 pm »
Thanks a lot for the explanation.
Having come from the Java stream, I assumed that the string in pascal is the same as the String in java.
In pascal it is an array where the length is stored in the 0th index.
Be aware that it's only for shortstring. Other string types stores it in negative indices. All in all, don't rely on implementation details.

tk

  • Sr. Member
  • ****
  • Posts: 361
Re: Is there is Windows Socket
« Reply #14 on: January 17, 2017, 04:42:54 pm »
If you really want to implement an HTTP server, consider using a pre-existing solution...

As it is most probably the case here, I would also recommend to use a pre-existing solution. Httpserv demo from Synapse library worked fine for me. Synapse is now easily available via Online Package Manager:  http://wiki.freepascal.org/Online_Package_Manager.

 

TinyPortal © 2005-2018