Cualquier cosa que valga la pena se hace en equipo

Cualquier cosa que valga la pena se hace en equipo

martes, 2 de noviembre de 2010

SOCKETS y PORTS




OBJETIVO


Sockets y Ports

Un Socket es una abstracción.-

Representa un punto de intercomunicación entre dos procesos (por ejemplo cliente y servidor). Los procesos pueden estar en el mismo host, nodo o computadora o en nodos diferentes.-

En un host pueden correr diferentes procesos brindando diferentes servicios. Por ejemplo servicios de HTTP, de Telnet, de FTP, de SMTP, etc. Cada uno de estos procesos tiene una dirección que lo identifica unívocamente respecto de los otros. Esta dirección se llama PORT.

Generalmente el servicio de HTTP se brinda en el port 80, el de Telnet en el 23, FTP en el 21 y SMTP en el 25. Decimos entonces que un PORT es una dirección relativa. Identifica al proceso pero no identifica al host en el que corre dicho proceso.

En una red TCP/IP como Internet cada host tiene una identificación única llamada número IP.

Un SOCKET es un número IP + un PORT. Por lo tanto es una dirección absoluta ya que identifica unívocamente un proceso en toda la red.


SOCKET

La especificación Windows Sockets define una interfaz de programación en Windows basada en el paradigma de sockets del BSD (Berkeley Software Distribution).-

Esta biblioteca, escrita en lenguaje C por ingenieros, profesores y estudiantes de la Universidad de Berkeley, fue pensada para la comunicación entre procesos que se ejecutan en la misma computadora o en computadoras de una misma red.-

EL software fue escrito originalmente como una API (Application Programming Interface) y el código que figura a continuación es un pequeño esqueleto que muestra como es la secuencia de inicio y cierre de un proceso de comunicación, pensando en un solo thread de ejecución:


#include <sys/types.h>

#include <sys/socket.h>

#include <netinet/in.h>

#include <arpa/inet.h>

#include <stdio.h>

#include <stdlib.h>

#include <strings.h>

int main()

{

//Inicio

int32_t i32SocketFD = socket(AF_INET, SOCK_STREAM, 0);


if(0 == i32SocketFD)

{

printf("no se puede crear el socket");

exit(-1);

}

struct sockaddr_in stSockAddr;

bzero(&stSockAddr, sizeof(stSockAddr));


stSockAddr.sin_family = AF_INET;

stSockAddr.sin_port = htons(1100);

stSockAddr.sin_addr.s_addr = htonl(INADDR_ANY);


//Enlace

if(-1 == bind(i32SocketFD,(struct sockaddr*) &stSockAddr, sizeof(stSockAddr)))

{

printf("error: bind fallido");

exit(-1);

}


//Escucha

if(-1 == listen(i32SocketFD, 10))

{

printf("error: listen fallido");

exit(-1);

}


for(; ;)

{

int32_t i32ConnectFD = accept(i32SocketFD, NULL, NULL);


if(0 > i32ConnectFD)

{

printf("error accept fallido");

exit(-1);

}

// acá es donde se debe escribir el código especifico ...

…..

//cierre

shutdown(i32ConnectFD, 2);

close(i32ConnectFD);

}

return 0;

}


¿Con que contamos en C#?

En C#, encontramos la funcionalidad de esta especificación, encapsulada en una clase llamada Socket, que es la que provee los métodos para la comunicación a través de la red así como la transferencia (sincrónica o asíncrona de datos).-

La clase Socket se encarga de proveer métodos y propiedades para la comunicación en red.-

Lo realmente interesante de esta clase es que encapsula la complejidad de la comunicación y una vez establecida el manejo de lo entrante y saliente se hace manejando flujos (streams).-

Estos flujos de comunicación pueden ser sincrónicos o asíncronos.-

Procesos de un solo thread y sincrónicos.-

Igual que en el ejemplo en lenguaje C visto al inicio de este manual, para procesos de un solo thread podemos utilizar los métodos específicos para modo de operación asíncrona: Listen(), Accept(), Bind(), Send() y Receive().-

Protocolo TCP

Estos métodos se utilizan en protocolos orientados a conexión (connection-oriented) como por ejemplo TCP.-

En este caso el servidor de la comunicación puede escuchar los pedidos con el método Listen .-

EL método Accept() procesa cualquier pedido de conexión entrante y retorna un Socket que es el que se utilizara para comunicar datos con el host remoto.-

Es este Socket el que se usa para llamar a los métodos Send() o Receive().-

Como en el caso general se desea indicar la dirección IP y el numero de puerto, se debe llamar al método Bind(), previo a llamar a Listen().-

En caso de no seguir esta secuencia, el proveedor del servicio subyacente asignara estos valores por nosotros. Es posible luego obtener la dirección IP y port asignados a nuestro Socket, del modo recién indicado.-

En el caso de querer conectarse a un servidor que esta escuchando requisiciones, se debe llamar al método Connect() y luego utilizar Send() y Receive() para envío y recepción de datos.-

// crear un socket

Socket listenSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

// enlazar el socket que escucha

IPAddress hostIP = (Dns.Resolve(IPAddress.Any.ToString())).AddressList[0];

IPEndPoint ep = new IPEndPoint(hostIP, port);

listenSocket.Bind(ep);

// escuchar

listenSocket.Listen(backlog);


Protocolo UDP

Si usamos un protocolo como UDP (protocolo sin conexión: connectionless), entonces no es necesario "escuchar" para conectarse. El método ReceiveFrom() es el que debe usarse para recibir los datagramas entrantes y el método SendTo() es el que debe usarse para el envio de datagramas al host remoto.

Procesos de mas de un thread y asincrónicos.-

Para procesar comunicaciones utilizando threads separados, existen una serie de mtodos pensados al efecto, es decir en un modo de operacion asincrono.-

Protocolo TCP

Cuando se utilizan protocolos orientados a la conexión (connection-oriented) como TCP, entonces debe utilizar los métodos Socket(), BeginConnect() y EndConnect() para comenzar las tareas de conexiones con el server que atiende los pedidos.-

El asincronismo en el envío y la recepción de datos (en los casos donde trabajamos con mas de un thread) necesita del uso de los métodos específicos de comunicación asincrónica. Estos son: BeginSend(),EndSend() , BeginReceive() y EndReceive(). Los pedidos de conexión entrante los debe procesar con los métodos: BeginAccept() y EndAccept().

Si estamos usando UDP entonces los métodos adecuados son para enviar datagramas son BeginSendTo() y EndSendTo() y para la recepción se debe usar BeginReceiveFrom() y EndReceiveFrom().

Usar un socket para comunicaciones con el protocolo HTTP

El ejemplo siguiente utiliza una clase Socket para enviar y recibir respuestas de un servidor HTTP.

Pensemos en un servidor WEB que esta corriendo en algún punto de la red.

El modo en el que escribimos el código requiere de algunos conceptos de cómo trabaja el protocolo HTTP, damos un repaso que consideramos adecuado.-

El protocolo HTTP

El Protocolo de Transferencia de Hipertexto (Hypertext Transfer Protocol) es un protocolo para comunicación entre un nodo cliente y otro nodo servidor.-

Su uso central es en la WEB, pero aclaremos que un servidor HTTP, puede recibir pedidos y enviar información sin necesidad de la existencia de browsers. Es decir es un mecanismo de comunicación que puede llegar a utilizarse en procesos puramente batch , no solo para interactivos.-

El protocolo esta montado sobre el servicio de conexión TCP/IP.

HTTP se basa en sencillas operaciones de solicitud/respuesta.

Un cliente establece una conexión con un servidor y envía un mensaje con los datos de la solicitud.-

El servidor responde con un mensaje similar, que contiene el estado de la operación y su posible resultado.-

La primera parte de una transacción HTTP es cuando un cliente crea y envia una solicitud al servidor.

Por ejemplo:

GET /index.html /HTTP 1.1

Es una pedido absolutamente correcto para un servidor HTTP activo

Existen tres verbos básicos que un cliente puede utilizar para dialogar con el servidor: GET, para recoger un objeto, POST, para enviar información al servidor y HEAD, para solicitar las características de un objeto (por ejemplo, la fecha de modificación de un documento HTML).

Todas las operaciones pueden adjuntar un objeto o recurso sobre el que actúan; cada objeto Web (documento HTML, fichero multimedia o aplicación CGI) es conocido por su URL (Uniform resources location podría concebirse como la extensión del concepto de nombre completo de un archivo (path)).

Cada operación HTTP implica una conexión con el servidor, que es liberada al término de la misma. (Esa es la verdadera esencia de Internet ¡!)

Es decir, en una operación se puede recoger un único objeto y no se mantienen estados.

Cada petición de un cliente a un servidor no es influida por las transacciones anteriores. El servidor trata cada petición como una operación totalmente independiente del resto.

El acceso a los servidores HTTP se realiza a través de las URLs, que empaquetan toda la información necesaria para localizar un determinado recurso en Internet. Cuando el servidor recibe una URL, a través del protocolo HTTP, la decodifica y devuelve al cliente la información correspondiente, que puede ser de dos tipos, en función del contenido de la URL:

Información estática: que se publica a base de situar los ficheros que la contienen en unos directorios especiales que define cada servidor. Este es el procedimiento que se ha utilizado hasta ahora.

Información dinámica: en este caso, el servidor HTTP arranca una aplicación utilizando la propia URL como parámetro de ejecución. El resultado de la ejecución de la aplicación será devuelto al cliente

El término 'información dinámica' se amplia cada vez más, a medida que se dispone de nuevas aplicaciones y tecnologías de publicación de información.

A través de estas nuevas tecnologías, es posible generar vistas a través del Web de elementos tan dispares como hojas de cálculo, bases de datos, agendas de reuniones, correos electrónicos e incluso periódicos completos, que se actualizan automáticamente en función de los cambios en el contenido de información original.

using System;

using System.Text;

using System.IO;

using System.Net;

using System.Net.Sockets;


public class mySocket

{

private static Socket connectSocket(string server, int port)

{

Socket s = null;

IPHostEntry iphe = null;

try

{

//

iphe = Dns.Resolve(server);

// Esta iteracion a traves de la lista de direcciones ( AddressList) es para obtener la

//llamada familia de direcciones ( AddressFamily) soportada.Esto evitara una excepcion en el caso

//en que la dirección IP no sea compatible con dicha familia.-

foreach (IPAddress ipad in iphe.AddressList)

{

IPEndPoint ipe = new IPEndPoint(ipad, port);

Socket tmpS =

new Socket(ipe.AddressFamily, SocketType.Stream, ProtocolType.Tcp);

tmpS.Connect(ipe);


if (tmpS.Connected)

{

s = tmpS;

break;

}

else

continue;

}

}


catch (SocketException e)

{

Console.WriteLine("SocketException !!!");

Console.WriteLine("Origen : " + e.Source);

Console.WriteLine("Mensaje : " + e.Message);

}

catch (Exception e)

{

Console.WriteLine("Exception atrapada!!!");

Console.WriteLine("Origen : " + e.Source);

Console.WriteLine("Mensaje : " + e.Message);

}

return s;


}


// este método consulta el contenido de la pagina Home del servidor indicado.

// y muestra el contenido recibido

private static string socketSendReceive(string server, int port)

{


//Preparamos para escribir al server

Encoding ASCII = Encoding.ASCII;

string Get = "GET / HTTP/1.1\r\nHost: " + server +

"\r\nConnection: Close\r\n\r\n";

Byte[] ByteGet = ASCII.GetBytes(Get);

Byte[] RecvBytes = new Byte[256];

String strRetPage = null;


// Ahora creamos un socket como conneccion con el server y el port indicado

Socket s = connectSocket(server, port);


if (s == null)

return ("Conneccion fallida");


// Ahi viaja el pedido al servidor.

s.Send(ByteGet, ByteGet.Length, 0);


// Aca viene la respuesta de la pagina home del server

Int32 bytes = s.Receive(RecvBytes, RecvBytes.Length, 0);


// Leer los primeros 256 bytes.Esto lo determina el uso de

//RecvBytes.Length en el método Receive

strRetPage = "Pagina Default HTML en el " + server + ":\r\n";

strRetPage = strRetPage + ASCII.GetString(RecvBytes, 0, bytes);


while (bytes > 0)

{

bytes = s.Receive(RecvBytes, RecvBytes.Length, 0);

strRetPage = strRetPage + ASCII.GetString(RecvBytes, 0, bytes);

}

return strRetPage;

}


public static void Main(string[] args)

{

string host;

int port = 91;


if (args.Length == 0)

// si no hay server indicado, usamos el nombre del host.

host = Dns.GetHostName();

else

host = args[0];

string result = socketSendReceive(host, port);

Console.WriteLine(result);

}

}

Vamos a hacer la prueba de este programa conectándolo contra un server WEB TOMCAT.


En mi equipo, como se observa, esta levantado en el puerto 8088.-

Si ejecuto el programa, colocando como parámetro en la línea de ejecución del programa, esta dirección.


Y lo ejecutamos, vemos la salida de texto que se muestra a continuación:


Por supuesto que es mejor verla con el browser ¡!


Usar sockets para armar un programa de mensajería entre pares (chat)

Vamos a construir una aplicación Windows que nos entregue una interfaz simple para comunicación. Queremos que sea un contenedor con dos paneles.

Uno que me muestre los mensajes que recibo y el otro que me permita escribir mensajes.-

La propia aplicación trabajara de dos modos diferenciados dependiendo de cómo se la invoque en la llamada. En un caso será servidor y en otro cliente.-

Alcanza con solo servidor para atender múltiples clientes.-

El esquema que armamos es el de "estrella". Es decir tal como armamos la aplicación todos los clientes pueden hablar con el servidor, pero no entre si.-

Una variante de este modo en el que el servidor atrape el pedido y lo derive u otro cliente de la red es relativamente sencillo de hacer basado en la tecnología mostrada en este ejemplo.-


Se habrá creado un proyecto con una serie de componentes como muestra el grafico


En este tipo de aplicaciones dentro del Form (Form1.cs), la IDE de .NET escribe algunos códigos de inicialización que no queremos para nuestro caso.-

Codigo en Form1.cs

Ingrese a código de Form1.Designer.cs y reemplácelo por el código que figura a continuación:


namespace UnChat

{

partial class Form1

{

/// <summary>

/// Required designer variable.

/// </summary>

private System.ComponentModel.IContainer components = null;



#region Windows Form Designer generated code


/// <summary>

/// Required method for Designer support - do not modify

/// the contents of this method with the code editor.

/// </summary>

private void InitializeComponent()

{


}


#endregion

}

}


Código en program.cs

Reemplace el código del modulo program.cs por el código que figura a continuación


using System;

using System.Collections.Generic;

using System.Windows.Forms;

using System.Net;

using System.Globalization;

using System.Net.Sockets;


namespace UnChat

{


static
class
Program

{


// -


private
static
IPEndPoint endPoint;


//Indica si esta actuando en modo servidor o cliente


private
static
bool client;



// Entrada al programa


public
static
void Main(String[] args)

{


// -


if (ParseArgs(args))

{


//


Talker talker = new
Talker(endPoint, client);



// Referencia del Talker dentro del Form


TalkForm form = new
TalkForm(talker);



// Arranca el talker

talker.Start();



// Arranca la apliacion con el Form


Application.Run(form);

}

}





// Parser de la linea de comandos


private
static
bool ParseArgs(String[] args)

{


try

{


if (args.Length == 0)

{

client = false;

endPoint = new
IPEndPoint(IPAddress.Any, 5150);


return
true;

}


if (args[0][0] != '/' && args[0][0] != '-')

{

ShowUsage();


return
false;

}


switch (Char.ToUpper(args[0][1], CultureInfo.InvariantCulture))

{


case
'L': //Listen: Escucha


int port = 5150;


if (args.Length > 1)

{

port = Convert.ToInt32(args[1]);

}

endPoint = new
IPEndPoint(IPAddress.Any, port);

client = false;


break;


case
'C'://Call: Llama

port = 5150;


String address = "127.0.0.1";

client = true;


if (args.Length > 1)

{

address = args[1];

port = Convert.ToInt32(args[2]);

}

endPoint = new
IPEndPoint(Dns.GetHostEntry(address).AddressList[0], port);


break;


default:

ShowUsage();


return
false;

}

}


catch

{

ShowUsage();


return
false;

}



return
true;

}


// Como se usa

private static void ComoUsarme()

{


MessageBox.Show("UnChat [switch] [parametros...]\n\n" +

" /L [port]\t\t-- Escucha en el port. Default: 5150\n" +

" /C [direccion] [port]\t-- Conecta a una direccion y port.\n\n" +

"Ejemplo Server - \n" +

"UnChat /L\n\n" +

"Ejemplo Client - \n" +

"UnChat /C NombreDeServidor 5150", "Uso de UnChat");

}

}

}


Código en Talker.cs


Creemos ahora la clase que representara al Talker



Y coloquemos dentro del archivo de esta clase el código que se indica a continuación:


using System;

using System.Collections.Generic;

using System.Text;

using System.Net;

using System.Net.Sockets;

using System.IO;

using System.Threading;


namespace UnChat

{

// Esta clase es una capa que encpasula a la clase Socket y le agrega

// algunas habilidades de chateo.-

class Talker : IDisposable

{

private Socket socket;


private TextReader reader;

private TextWriter writer;


bool client;

IPEndPoint endPoint;


private String prevSendText;

private String prevReceiveText;

private String statusText;


private Status status;


// Constructor

public Talker(IPEndPoint endPoint, bool client)

{

this.endPoint = endPoint;

this.client = client;


socket = null;

reader = null;

writer = null;


statusText = prevSendText = prevReceiveText = String.Empty;

}


// -

~Talker()

{

Dispose();

}


// Este es un modo ordenado y seguro de liberar todos

//los recursos que se usaron en el momento en que se baja

//la aplicacion

public void Dispose()

{

GC.SuppressFinalize(this);

if (reader != null)

{

reader.Close();

reader = null;

}

if (writer != null)

{

writer.Close();

writer = null;

}

if (socket != null)

{

socket.Close();

socket = null;

}

}


// Clase delegate y evento

public delegate

void NotificationCallback(Notification notify, Object data);

public event NotificationCallback Notifications;


// enum de los tipos de notificaciones

public enum Notification

{

Initialized = 1,

StatusChange,

ReceivedRefresh,

ReceivedAppend,

End,

Error

}


// enum de los posibles estados

public enum Status

{

Escuchando,

Conectado,

Cliente

}



// EL inicio de una instancia de la clase es un thread

//que se encola en el pool de threads

public void Start()

{

ThreadPool.QueueUserWorkItem(new WaitCallback(EstablishSocket));

}


// Envio de texto a la coneccion remota

public void EnviaMensaje(String newText)

{

String send;

// es un agregado al texto (append)

if ((prevSendText.Length <= newText.Length) && String.CompareOrdinal(

newText, 0, prevSendText, 0, prevSendText.Length) == 0)

{

String append = newText.Substring(prevSendText.Length);

send = String.Format("A{0}:{1}", append.Length, append);


}// o reemplazo completo

else

{

send = String.Format("R{0}:{1}", newText.Length, newText);

}

// Envio datos y hace flush

writer.Write(send);

writer.Flush();

// Guardar el texto para comparar si es necesario

prevSendText = newText;

}


// Notifica un estado

private void SetStatus(Status status)

{

this.status = status;

Notifications(Notification.StatusChange, status);

}



// Establecer una coneccion via socket y comenzar la recepcion

private void EstablishSocket(Object state)

{

NetworkStream stream = null;

try

{

// Si no es un cliente, entonces levantar una Escucha (listener)

if (!client)

{

Socket listener;


try

{

listener = new Socket(AddressFamily.InterNetwork,

SocketType.Stream, ProtocolType.Tcp);

listener.Blocking = true;

listener.Bind(endPoint);

SetStatus(Status.Escuchando);

listener.Listen(0);

socket = listener.Accept();

listener.Close();

stream = new NetworkStream(socket);

reader = new StreamReader(stream);

writer = new StreamWriter(stream);

writer.Write("WINTALK .NET");

writer.Flush();

}

catch (SocketException e)

{


// Este error indica que alguien esta usando el puerto

//Asumamos que en ese caso se debe intentar conectarse como un cliente

//pensando que ya hay un server para los nodos de la red

if (e.ErrorCode == 10048)

{

client = true;

endPoint = new IPEndPoint(

Dns.Resolve("127.0.0.1").AddressList[0], endPoint.Port);

}

else

{

Notifications(

Notification.Error,

"Error al inicializar el Socket:\n" + e.ToString());

}

}

}



// Intenta coneccion como cliente

if (client)

{

SetStatus(Status.Cliente);

Socket temp = new

Socket(AddressFamily.InterNetwork,

SocketType.Stream, ProtocolType.Tcp);

temp.Blocking = true;

temp.Connect(endPoint);

socket = temp;

socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReceiveTimeout, 5000);

socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.SendTimeout, 5000);

stream = new NetworkStream(socket);

reader = new StreamReader(stream);

writer = new StreamWriter(stream);

char[] handshake = new char[12];


try

{

reader.Read(handshake, 0, 12);

string sHandShake = new string(handshake);


if (!(reader.Read(handshake, 0, 12) > 0 && sHandShake == "WINTALK .NET"))

{

socket.Close();

socket = null;

}

else

{

socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReceiveTimeout, 0);

socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.SendTimeout, 0);

}

}

catch

{

socket.Close();

socket = null;

}

}


// Si establecimos el socket, comenzar a chatear

if (socket != null)

{

SetStatus(Status.Conectado);

Notifications(Notification.Initialized, this);

// -

//NetworkStream.Read()es un metodo llamado por el metodo ReceiveTalk

//El primer metodo genera una excepcion cuando se cierra la coneccion remota

//La excepcion se maneja en el catch

ReceiveTalk();


// Por aca pasa cuando NetworkStream.Read() retorna un cero (algo que hace

//en alguans versiones del SO

Notifications(Notification.End, "La coneccion remota se cerro.");

}

else

{

Notifications(Notification.Error,

"Falla al establecer el , Verifique si especifico el port correcto");

}

}

catch (IOException e)

{

SocketException sockExcept = e.InnerException as SocketException;

if (sockExcept != null && 10054 == sockExcept.ErrorCode)

{

Notifications(Notification.End, "La coneccion remota se cerro.");

}

else

{

if (Notifications != null)

Notifications(Notification.Error, "Error :\n" + e.Message);

}

}

catch (Exception e)

{

Notifications(Notification.Error, "Error:\n" + e.Message);

}

}



// Recibe la comunicacion del cliente remoto

private void ReceiveTalk()

{

char[] commandBuffer = new char[20];

char[] oneBuffer = new char[1];

int readMode = 1;

int counter = 0;

StringBuilder text = new StringBuilder();


while (readMode != 0)

{

if (reader.Read(oneBuffer, 0, 1) == 0)

{

readMode = 0;

continue;

}


switch (readMode)

{

case 1:

if (counter == commandBuffer.Length)

{

readMode = 0;

continue;

}

if (oneBuffer[0] != ':')

{

commandBuffer[counter++] = oneBuffer[0];

}

else

{

counter = Convert.ToInt32(

new String(commandBuffer, 1, counter - 1));

if (counter > 0)

{

readMode = 2;

text.Length = 0;

}

else if (commandBuffer[0] == 'R')

{

counter = 0;

prevReceiveText = String.Empty;

Notifications(Notification.ReceivedRefresh, prevReceiveText);

}

}

break;

case 2:

text.Append(oneBuffer[0]);

if (--counter == 0)

{

switch (commandBuffer[0])

{

case 'R':

prevReceiveText = text.ToString();

Notifications(Notification.ReceivedRefresh, prevReceiveText);

break;

default:

string newText = text.ToString();

prevReceiveText += newText;

Notifications(Notification.ReceivedAppend, newText);

break;

}

readMode = 1;


}

break;

default:

readMode = 0;

continue;

}

}

}

}

}

Como ejecutar la aplicación


Usar una sesión como cliente y otra como servidor

Para eso generar dos archivos .bat (llamémoslos ChatCliente.bat y ChatServer.bat) que inicien cada uno una sesión del programa


Por ejemplo para ChatCliente.bat

UnChat.exe /C m3nb02 5150

Que significa que el programa desea actuar como Cliente (de allí la letra C) del equipo m3nb02 (es el nombre de mi equipo en esta red en la que estoy trabajando) y "hablar" por el port 5150.-


Por ejemplo para ChatServer.bat


UnChat.exe /L 5150

Que significa que el programa desea actuar como Server (La letra L por Listen) y "hablar" por el port 5150.-


Sockets y Ports

El protocolo FTP

Codigos de retorno de FTP

Code

Explanation

100

Series: The requested action is being initiated, expect another reply before proceeding with a new command.

110

Restart marker replay . In this case, the text is exact and not left to the particular implementation; it must read: MARK yyyy = mmmm where yyyy is User-process data stream marker, and mmmm server's equivalent marker (note the spaces between markers and "=").

120

Service ready in nnn minutes.

125

Data connection already open; transfer starting.

150

File status okay; about to open data connection.

200

Command okay.

202

Command not implemented, superfluous at this site.

211

System status, or system help reply.

212

Directory status.

213

File status.

214

Help message.On how to use the server or the meaning of a particular non-standard command. This reply is useful only to the human user.

215

NAME system type. Where NAME is an official system name from the list in the Assigned Numbers document.

220

Service ready for new user.

221

Service closing control connection.

225

Data connection open; no transfer in progress.

226

Closing data connection. Requested file action successful (for example, file transfer or file abort).

227

Entering Passive Mode (h1,h2,h3,h4,p1,p2).

228

Entering Long Passive Mode (long address, port).

229

Entering Extended Passive Mode (port).

230

User logged in, proceed. Logged out if appropriate.

231

User logged out; service terminated.

232

Logout command noted, will complete when transfer done.

250

Requested file action okay, completed.

257

"PATHNAME" created.

331

User name okay, need password.

332

Need account for login.

350

Requested file action pending further information

421

Service not available, closing control connection. This may be a reply to any command if the service knows it must shut down.

425

Can't open data connection.

426

Connection closed; transfer aborted.

434

Requested host unavailable.

450

Requested file action not taken.

451

Requested action aborted. Local error in processing.

452

Requested action not taken. Insufficient storage space in system.File unavailable (e.g., file busy).

500

Syntax error, command unrecognized. This may include errors such as command line too long.

501

Syntax error in parameters or arguments.

502

Command not implemented.

503

Bad sequence of commands.

504

Command not implemented for that parameter.

530

Not logged in.

532

Need account for storing files.

550

Requested action not taken. File unavailable (e.g., file not found, no access).

551

Requested action aborted. Page type unknown.

552

Requested file action aborted. Exceeded storage allocation (for current directory or dataset).

553

Requested action not taken. File name not allowed.