Sockets: Difference between revisions

From Rosetta Code
Content added Content deleted
(added slate language)
(+AutoHotkey)
Line 26: Line 26:
end;
end;
</lang>
</lang>
=={{header|AutoHotkey}}==
modified from
[http://www.autohotkey.com/forum/topic13829.html script] by zed gecko.
<lang autohotkey>Network_Port = 256
Network_Address = 127.0.0.1
NewData := false
DataReceived =
GoSub, Connection_Init
SendData(socket,"hello socket world")
return

Connection_Init:
OnExit, ExitSub

socket := ConnectToAddress(Network_Address, Network_Port)
if socket = -1
ExitApp

Process, Exist
DetectHiddenWindows On
ScriptMainWindowId := WinExist("ahk_class AutoHotkey ahk_pid " . ErrorLevel)
DetectHiddenWindows Off

NotificationMsg = 0x5556
OnMessage(NotificationMsg, "ReceiveData")

FD_READ = 1
FD_CLOSE = 32
if DllCall("Ws2_32\WSAAsyncSelect", "UInt", socket, "UInt", ScriptMainWindowId, "UInt", NotificationMsg, "Int", FD_READ|FD_CLOSE)
{
MsgBox % "WSAAsyncSelect() indicated Winsock error " . DllCall("Ws2_32\WSAGetLastError")
ExitApp
}

return


ConnectToAddress(IPAddress, Port)
{
VarSetCapacity(wsaData, 32)
result := DllCall("Ws2_32\WSAStartup", "UShort", 0x0002, "UInt", &wsaData)
if ErrorLevel
{
MsgBox WSAStartup() could not be called due to error %ErrorLevel%. Winsock 2.0 or higher is required.
return -1
}
if result
{
MsgBox % "WSAStartup() indicated Winsock error " . DllCall("Ws2_32\WSAGetLastError")
return -1
}
AF_INET = 2
SOCK_STREAM = 1
IPPROTO_TCP = 6
socket := DllCall("Ws2_32\socket", "Int", AF_INET, "Int", SOCK_STREAM, "Int", IPPROTO_TCP)
if socket = -1
{
MsgBox % "socket() indicated Winsock error " . DllCall("Ws2_32\WSAGetLastError")
return -1
}
SizeOfSocketAddress = 16
VarSetCapacity(SocketAddress, SizeOfSocketAddress)
InsertInteger(2, SocketAddress, 0, AF_INET)
InsertInteger(DllCall("Ws2_32\htons", "UShort", Port), SocketAddress, 2, 2)
InsertInteger(DllCall("Ws2_32\inet_addr", "Str", IPAddress), SocketAddress, 4, 4)
if DllCall("Ws2_32\connect", "UInt", socket, "UInt", &SocketAddress, "Int", SizeOfSocketAddress)
{
MsgBox % "connect() indicated Winsock error " . DllCall("Ws2_32\WSAGetLastError") . "?"
return -1
}
return socket
}

ReceiveData(wParam, lParam)
{
global DataReceived
global NewData
socket := wParam
ReceivedDataSize = 4096
Loop
{
VarSetCapacity(ReceivedData, ReceivedDataSize, 0)
ReceivedDataLength := DllCall("Ws2_32\recv", "UInt", socket, "Str", ReceivedData, "Int", ReceivedDataSize, "Int", 0)
if ReceivedDataLength = 0
ExitApp
if ReceivedDataLength = -1
{
WinsockError := DllCall("Ws2_32\WSAGetLastError")
if WinsockError = 10035
{
DataReceived = %TempDataReceived%
NewData := true
return 1
}
if WinsockError <> 10054
MsgBox % "recv() indicated Winsock error " . WinsockError
ExitApp
}
if (A_Index = 1)
TempDataReceived =
TempDataReceived = %TempDataReceived%%ReceivedData%
}
return 1
}

SendData(wParam,SendData)
{
socket := wParam
SendDataSize := VarSetCapacity(SendData)
SendDataSize += 1
sendret := DllCall("Ws2_32\send", "UInt", socket, "Str", SendData, "Int", SendDatasize, "Int", 0)
}

InsertInteger(pInteger, ByRef pDest, pOffset = 0, pSize = 4)
{
Loop %pSize%
DllCall("RtlFillMemory", "UInt", &pDest + pOffset + A_Index-1, "UInt", 1, "UChar", pInteger >> 8*(A_Index-1) & 0xFF)
}

ReceiveProcedure:
if NewData
GuiControl, , ReceivedText, %DataReceived%
NewData := false
Return

ExitSub:
DllCall("Ws2_32\WSACleanup")
ExitApp
</lang>


=={{header|C}}==
=={{header|C}}==

Revision as of 20:17, 24 June 2009

Task
Sockets
You are encouraged to solve this task according to the task description, using any language you may know.

For this exercise a program is open a socket to localhost on port 256 and send the message "hello socket world" before closing the socket. Catching any exceptions or errors is not required.

Ada

Library: GNAT RTL

<lang ada> with GNAT.Sockets; use GNAT.Sockets;

procedure SocketSend is

  procedure sendData (IP : String; Msg : String) is
     Client  : Socket_Type;
     Address : Sock_Addr_Type;
     Channel : Stream_Access; 
  begin
     Create_Socket (Client);
     Address.Addr := Inet_Addr(ip);
     Address.Port := 256;
     Connect_Socket (Client, Address);
     Channel := Stream (Client);
     String'Write (Channel, Msg);
     Close_Socket (Client);      
  end;

begin

  Initialize;
  sendData ("127.0.0.1","Hello Socket World");

end; </lang>

AutoHotkey

modified from script by zed gecko. <lang autohotkey>Network_Port = 256 Network_Address = 127.0.0.1 NewData := false DataReceived = GoSub, Connection_Init SendData(socket,"hello socket world") return

Connection_Init: OnExit, ExitSub

socket := ConnectToAddress(Network_Address, Network_Port) if socket = -1

   ExitApp

Process, Exist DetectHiddenWindows On ScriptMainWindowId := WinExist("ahk_class AutoHotkey ahk_pid " . ErrorLevel) DetectHiddenWindows Off

NotificationMsg = 0x5556 OnMessage(NotificationMsg, "ReceiveData")

FD_READ = 1 FD_CLOSE = 32 if DllCall("Ws2_32\WSAAsyncSelect", "UInt", socket, "UInt", ScriptMainWindowId, "UInt", NotificationMsg, "Int", FD_READ|FD_CLOSE) {

   MsgBox % "WSAAsyncSelect() indicated Winsock error " . DllCall("Ws2_32\WSAGetLastError")
   ExitApp

}

return


ConnectToAddress(IPAddress, Port) {

   VarSetCapacity(wsaData, 32)
   result := DllCall("Ws2_32\WSAStartup", "UShort", 0x0002, "UInt", &wsaData)
   if ErrorLevel
   {
       MsgBox WSAStartup() could not be called due to error %ErrorLevel%. Winsock 2.0 or higher is required.
       return -1
   }
   if result
   {
       MsgBox % "WSAStartup() indicated Winsock error " . DllCall("Ws2_32\WSAGetLastError")
       return -1
   }
   AF_INET = 2
   SOCK_STREAM = 1
   IPPROTO_TCP = 6
   socket := DllCall("Ws2_32\socket", "Int", AF_INET, "Int", SOCK_STREAM, "Int", IPPROTO_TCP)
   if socket = -1
   {
       MsgBox % "socket() indicated Winsock error " . DllCall("Ws2_32\WSAGetLastError")
       return -1
   }
   SizeOfSocketAddress = 16
   VarSetCapacity(SocketAddress, SizeOfSocketAddress)
   InsertInteger(2, SocketAddress, 0, AF_INET)
   InsertInteger(DllCall("Ws2_32\htons", "UShort", Port), SocketAddress, 2, 2)
   InsertInteger(DllCall("Ws2_32\inet_addr", "Str", IPAddress), SocketAddress, 4, 4)
   if DllCall("Ws2_32\connect", "UInt", socket, "UInt", &SocketAddress, "Int", SizeOfSocketAddress)
   {
       MsgBox % "connect() indicated Winsock error " . DllCall("Ws2_32\WSAGetLastError") . "?"
       return -1
   }
   return socket

}

ReceiveData(wParam, lParam) {

   global DataReceived
   global NewData
   socket := wParam
   ReceivedDataSize = 4096
   Loop
   {
       VarSetCapacity(ReceivedData, ReceivedDataSize, 0)
       ReceivedDataLength := DllCall("Ws2_32\recv", "UInt", socket, "Str", ReceivedData, "Int", ReceivedDataSize, "Int", 0)
       if ReceivedDataLength = 0
           ExitApp
       if ReceivedDataLength = -1
       {
           WinsockError := DllCall("Ws2_32\WSAGetLastError")
           if WinsockError = 10035
           {
               DataReceived = %TempDataReceived%
               NewData := true
               return 1
           }
           if WinsockError <> 10054
               MsgBox % "recv() indicated Winsock error " . WinsockError
           ExitApp
       }
       if (A_Index = 1)
           TempDataReceived =
       TempDataReceived = %TempDataReceived%%ReceivedData%
   }
   return 1

}

SendData(wParam,SendData) {

   socket := wParam
   SendDataSize := VarSetCapacity(SendData)
   SendDataSize += 1
   sendret := DllCall("Ws2_32\send", "UInt", socket, "Str", SendData, "Int", SendDatasize, "Int", 0)

}

InsertInteger(pInteger, ByRef pDest, pOffset = 0, pSize = 4) {

   Loop %pSize%
       DllCall("RtlFillMemory", "UInt", &pDest + pOffset + A_Index-1, "UInt", 1, "UChar", pInteger >> 8*(A_Index-1) & 0xFF)

}

ReceiveProcedure:

   if NewData
       GuiControl, , ReceivedText, %DataReceived%
   NewData := false

Return

ExitSub: DllCall("Ws2_32\WSACleanup") ExitApp </lang>

C

Works with: POSIX version .1-2001
Works with: gcc version 4.2.2

With little changes it could work on MS Windows (without Cygwin) too. But I don't know exactly how. I have tested it using the netcat -l -p 256.

<lang c>#include <stdio.h>

  1. include <string.h>
  2. include <sys/types.h>
  3. include <sys/socket.h>
  4. include <netdb.h>

char msg[] = "hello socket world";

int main() {

  int r, i, sock, len, slen;
  char *pm = msg;
  struct addrinfo hints, *res;
  
  memset(&hints, 0, sizeof(struct addrinfo));
  hints.ai_family = AF_UNSPEC;
  hints.ai_socktype = SOCK_STREAM;
  
  r = getaddrinfo("localhost", "256", &hints, &res);
  if ( r == 0 )
  {
      sock = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
      if ( sock >= 0 )
      {
          if ( connect(sock, res->ai_addr, res->ai_addrlen) >= 0 )
          {
              do
              {
                 len = strlen(pm);
                 slen = send(sock, pm, len, 0);
                 pm += slen;
              } while ( slen < len );
          }
          close(sock);
      }
      freeaddrinfo(res);
  }

}</lang>

C#

<lang csharp>using System; using System.IO; using System.Net.Sockets;

class Program {

   static void Main(string[] args) {
       TcpClient tcp = new TcpClient("localhost", 256);
       StreamWriter writer = new StreamWriter(tcp.GetStream());
       writer.Write("hello socket world");
       writer.Flush();
       tcp.Close();
   }

}</lang>

D

<lang d>module socket ; import std.stdio ; import std.socket ; version(Win32) {

 // For Win32 systems, need to link with ws2_32.lib. 
 pragma(lib, "ws2_32.lib") ; 

} void main() {

 auto socket = new Socket(AddressFamily.INET, SocketType.STREAM) ;
 socket.connect(new InternetAddress("localhost",256)) ;
 writefln(socket.send(cast(void[])"Hello socket world"), " bytes sent.") ;
 socket.close() ;

}</lang>

Haskell

import Network

main = withSocketsDo $ sendTo "localhost" (PortNumber $ toEnum 256) "hello socket world"

Icon

link cfunc
procedure main ()
   hello("localhost", 1024)
end
procedure hello (host, port)
   write(tconnect(host, port) | stop("unable to connect to", host, ":", port) ,  "Hello socket world")
end

IDL

 socket, unit, 'localhost',256,/get_lun  
 printf,unit,"Hello socket world" 
 close, unit 

"Well-known" port numbers (under 1024 -- such as 256) can also be specified by name (in this case 'RAP').

If there is no listener on this port, this will hang for a while before timing out.

Java

<lang java>import java.net.*; public class SocketSend {

 public static void main(String args[]) throws java.io.IOException {
   sendData("localhost", "Hello Socket World");
 }
 public static void sendData(String host, String msg) throws java.io.IOException{
   Socket sock = new Socket( host, 256 );
   sock.getOutputStream().write(msg.getBytes());
   sock.getOutputStream().flush();
   sock.close();
 }

}</lang> Encapsulating the Socket's OutputStream in a PrintStream (for data) or PrintWriter (for text) may be easier in more complex programs for their auto-flush abilities and their overloaded print and println methods. The write method from the original OutputStream will still be available.

OCaml

<lang ocaml>open Unix

let init_socket addr port =

 let inet_addr = (gethostbyname addr).h_addr_list.(0) in
 let sockaddr = ADDR_INET (inet_addr, port) in
 let sock = socket PF_INET SOCK_STREAM 0 in
 connect sock sockaddr;
 (* convert the file descriptor into high-level channels: *)
 let outchan = out_channel_of_descr sock in
 let inchan = in_channel_of_descr sock in
 (inchan, outchan)</lang>

<lang ocaml>let () =

 let ic, oc = init_socket "localhost" 256 in
 output_string oc "Hello Socket World";
</lang>

Perl

<lang perl>use Socket;

$host = gethostbyname('localhost'); $in = sockaddr_in(256, $host); $proto = getprotobyname('tcp'); socket(Socket_Handle, AF_INET, SOCK_STREAM, $proto); connect(Socket_Handle, $in); send(Socket_Handle, 'Hello socket world', 0, $in); close(Socket_Handle);</lang>

Object oriented version. <lang perl>use Socket::Class;

$sock = Socket::Class->new(

 'remote_port' => 256,

) || die Socket::Class->error; $sock->send('Hello socket world'); $sock->free;</lang>

Python

<lang python>import socket sock = socket.socket(AF_INET, SOCK_STREAM) sock.connect(("localhost", 256)) sock.sendall("hello socket world") sock.close()</lang>

Rhope

Works with: Rhope version alpha 1
Socket Send(0,0)
|:
    [New@Net Client["localhost",256]]Put String["hello socket world"]
:|

The connection is automatically closed when the object is freed.

Ruby

<lang ruby>require 'socket' sock = TCPSocket.open("localhost", 256) sock.write("hello socket world") sock.close</lang>

Seed7

$ include "seed7_05.s7i";
  include "socket.s7i";

const proc: main is func
  local
    var file: sock is STD_NULL;
  begin
    sock := openInetSocket(256);
    writeln(sock, "hello socket world");
    close(sock);
  end func;


Slate

This uses fairly verbose and low level messages. This will probably be simplified in the future.

<lang slate>

[ | socket |

 [ | addr stream |
   addr: (Net SocketAddress newOn: '127.0.0.1:256').
   socket: (Net Socket newFor: addr domain type: Net Socket Types Stream protocol: Net Socket Protocols Default).
   socket connectTo: addr.
   stream: (Net SocketStream newOn: socket).
   stream nextPutAll: ('hello socket world' as: ByteArray)
 ] ensure: [socket close]

] do. </lang>

Smalltalk

Works with: GNU Smalltalk

This is taken from here with few modification to fit the task better.

<lang smalltalk>PackageLoader fileInPackage: 'TCP'!

Object subclass: #HelloSocket

 instanceVariableNames: 'ss'
 classVariableNames: 
 poolDictionaries: 
 category: 'SimpleEcho'!

!HelloSocket class methodsFor: 'instance creation'!

port: anInteger

 | ses |
 ses := super new.
 ses init: anInteger.
 ^ses

!!

!HelloSocket methodsFor: 'instance initialization'!

init: anInteger

 ss := (TCP.ServerSocket port: anInteger).
 ^self

!!

!HelloSocket methodsFor: 'running'!

run

 | s |
 [
   ss waitForConnection.
   s := (ss accept).
   [self handleSocket: s] fork
 ] repeat

!!

!HelloSocket methodsFor: 'handling'!

handleSocket: s

   | msg |
   msg := 'hello socket world'.
   msg displayOn: s.
   (String with: (Character value: 10)) displayOn: s.
   s flush

!!

Smalltalk at: #helloServer put: (HelloSocket port: 2560).

helloServer run.</lang>

Tcl

<lang tcl>set io [socket localhost 256] puts -nonewline $io "Hello socket world" close $io</lang>

Toka

 needs sockets
 
 #! A simple abstraction layer that makes writing trivial servers easy
 value| server.socket server.connection server.action |
 [ ( n- )   pBind to server.socket ] is server.setSocket
 [ ( - )    server.socket pAccept to server.connection ] is server.acceptConnection
 [ ( - )    server.connection pClose drop ] is server.closeConnection
 [ ( $- )   >r server.connection r> string.getLength pWrite drop ] is server.send
 [ ( an- )  server.connection -rot pRead drop ] is server.recieve
 [ ( qn- )  swap to server.action server.setSocket
   [ server.acceptConnection server.action invoke server.closeConnection TRUE ] whileTrue ] is server.start
 
 #! The actual server
 [ " hello socket world" server.send ] 256 server.start

UnixPipes

(echo "Hello World" | nc localhost 256 | exit 0)

UNIX Shell

Using the program netcat (nc)

echo "hello socket world" | netcat localhost 256