Quiero usar VS2005-C# para crear un software de chat en la red de área local
Desarrollo de programas de red C#.Net: Socket
Microsoft.Net Framework proporciona métodos en capas, escalables y controlados para que las aplicaciones accedan a Internet
Servicios de red administrados, su espacio de nombres System.Net y System.Net.Sockets contienen clases ricas que se pueden utilizar para desarrollar una variedad de aplicaciones de red. La estructura jerárquica adoptada por las clases .Net permite que las aplicaciones accedan a la red en diferentes niveles de control. Los desarrolladores pueden elegir programar para diferentes niveles según sea necesario. Estos niveles cubren casi todas las necesidades. Internet: desde sockets hasta solicitudes/respuestas ordinarias. Más importante aún, esta estratificación es extensible y puede adaptarse a las necesidades en constante expansión de Internet.
Sin tener en cuenta la arquitectura de 7 capas del modelo ISO/OSI, mirando solo el nivel lógico del modelo TCP/IP, se puede considerar que la clase .Net
contiene 3 niveles: capa de solicitud/respuesta, capa de protocolo de aplicación, capa de transporte. WebReqeust y
WebResponse representan la capa de solicitud/respuesta. Las clases que admiten Http, Tcp y Udp forman la capa de protocolo de aplicación
, mientras que la clase Socket está en la capa de transporte.
La capa de transporte se encuentra en la parte inferior de esta estructura. Cuando la capa de protocolo de aplicación y la capa de solicitud/respuesta superior no pueden satisfacer las necesidades especiales del programa de aplicación,
esta capa. Es necesario utilizar la programación de socket.
En .Net, el espacio de nombres System.Net.Sockets proporciona a los desarrolladores que necesitan controlar estrictamente el acceso a la red
una implementación administrada de la interfaz Windows Sockets (Winsock). Todas las demás clases de acceso a la red en el espacio de nombres System.Net se basan en esta implementación de Socket, como las clases TCPClient, TCPListener y UDPClient que encapsulan la creación de información detallada de las conexiones TCP y UDP de Internet;
La clase NetworkStream proporciona flujos de datos básicos para el acceso a la red, etc. Los sockets se pueden ver en muchos servicios comunes de Internet
, como Telnet, Http, correo electrónico, Echo, etc. Aunque estos servicios tienen diferentes definiciones de protocolos de comunicación, sus La transmisión básica utiliza Socket.
De hecho, Socket puede considerarse como un canal de datos como un Stream. Este canal se establece entre la aplicación (cliente) y el servidor remoto, luego la lectura (recepción) y la escritura (envío) de datos. /p>
ambos se realizan para este canal.
Se puede ver que después de crear un objeto Socket en el lado de la aplicación o en el lado del servidor, puede usar el método
Send/SentTo para enviar datos al Socket conectado, o usar el método Recibir/ReceiveFrom.
No se pueden recibir datos del Socket conectado.
Para la programación de Socket, la clase Socket del marco .NET es el alojamiento del servicio de socket proporcionado por el. Winsock32 API
Versión del código. Se proporcionan varios métodos para implementar la programación de red y, en la mayoría de los casos, los métodos de la clase Socket simplemente agrupan los datos en sus copias nativas de Win32 y manejan las comprobaciones de seguridad necesarias.
Si
está familiarizado con las funciones de la API de Winsock, será muy fácil usar la clase Socket para escribir programas de red. Por supuesto,
si nunca ha estado expuesto a ella. No será demasiado difícil. Siga los pasos a continuación. Encontrará que existen reglas para desarrollar aplicaciones de red de Windows utilizando la clase Socket y que siguen aproximadamente los mismos pasos en la mayoría de los casos.
Antes de usarlo, primero debe crear una instancia del objeto Socket. Esto se puede lograr a través del constructor
de la clase Socket:
public. Socket(AddressFamily AddressFamily, SocketType
socketType, ProtocolType protocolType);
Entre ellos, el parámetro AddressFamily especifica el esquema de direccionamiento utilizado por Socket y el parámetro socketType especifica el tipo de Socket. protocoloType El parámetro especifica el protocolo utilizado por el Socket.
La siguiente declaración de ejemplo crea un socket que se puede utilizar para comunicarse a través de una red basada en TCP/IP, como Internet.
Socket s = new Socket(AddressFamily.InterNetwork, SocketType.Stream,
ProtocolType.Tcp
Para usar UDP en lugar de TCP, los cambios deben realizarse se hará tipo de protocolo, como se muestra en el siguiente ejemplo:
Socket s = new Socket(AddressFamily.InterNetwork, SocketType.Dgram,
ProtocolType.Udp
<); p> Una vez creado el Socket, en el lado del cliente, podrá conectarse al servidor especificado a través del método Connect,y enviar datos al servidor remoto a través del método Send/SendTo, y luego puede usar
Receive /ReceiveFrom recibe datos del servidor, debe usar el método Bind para vincular la interfaz especificada para asociar el Socket con un punto final local y escuchar la interfaz. a través de la solicitud del método Listen
en el cliente, cuando escuche la conexión del usuario, llame a Accept para completar la operación de conexión y cree un nuevo Socket
para manejar la solicitud de conexión entrante. Después de usar el Socket, recuerde usar el método Shutdown para deshabilitar el Socket y use el método Close para cerrar el Socket. Los métodos/funciones utilizadas son:
Método Socket.Connect: Establece una conexión con el dispositivo remoto
public void Connect(EndPoint remoteEP) (con método sobrecargado)
Método Socket.Send: envía datos al Socket conectado comenzando desde la posición indicada en los datos.
public int Send(byte[], int, SocketFlags); (con métodos sobrecargados)
El método Socket.SendTo envía datos a un punto final específico.
public int SendTo(byte[], EndPoint); (método sobrecargado)
Método Socket.Receive: recibe datos del Socket conectado a una ubicación específica en el búfer de recepción.
public int Recibir(byte[], int, SocketFlags);
Método Socket.ReceiveFrom: recibe datos en una ubicación específica en el búfer de datos y almacena el punto final.
public int ReceiverFrom(byte[], int, SocketFlags, ref EndPoint);
Método Socket.Bind: asocia el Socket con un punto final local:
public void Bind(EndPoint localEP);
Método Socket.Listen: coloque el Socket en estado de escucha.
public void Listen( int backlog );
Método Socket.Accept: crea un nuevo Socket para manejar las solicitudes de conexión entrantes.
public Socket Accept();
Método Socket.Shutdown: deshabilita el envío y la recepción en un determinado Socket
public void Shutdown( SocketShutdown how ); p>
p>
Método Socket.Close: forzar el cierre de la conexión Socket
public void Close()
Como se puede ver, muchos de los anteriores Los métodos contienen parámetros del tipo EndPoint. En Internet, TCP/IP utiliza una dirección de red y un número de puerto de servicio para identificar de forma única un dispositivo. La dirección de red identifica un dispositivo específico en la red;
El número de puerto identifica el servicio específico en ese dispositivo al que conectarse. La combinación de dirección de red y puerto de servicio se denomina punto final. En el marco .NET, este punto final está representado por la clase EndPoint, que proporciona una abstracción para representar recursos o servicios de red. Se utiliza para marcar información como direcciones de red. .Net también define descendientes de
EndPoint para cada familia de direcciones admitidas; para las familias de direcciones IP, la clase es IPEndPoint. La clase IPEndPoint contiene la información de puerto y host requerida por la aplicación para conectarse al servicio en el host. Al combinar la dirección IP del host del servicio y el número de puerto, la clase IPEndPoint forma el enlace al servicio.
Cuando se utiliza la clase IPEndPoint, la dirección IP de la computadora está inevitablemente involucrada. Hay dos clases en .Net que pueden
obtener instancias de direcciones IP:
IPAddress. Clase: la clase IPAddress contiene la dirección de la computadora en la red IP. Su método Parse convierte una cadena de dirección IP en una instancia de IPAddress. La siguiente declaración crea una instancia de IPAddress:
IPAddress myIP = IPAddress.Parse("192.168.1.2");
Clase Dns: proporcionada a aplicaciones que utilizan servicios de Internet TCP/IP. Servicios de nombres.
Su método Resolve consulta a un servidor DNS para asignar un nombre de dominio fácil de usar (como "host.contoso.com") a una dirección numérica de Internet (como 192.168.1.1). Método de resolución Devuelve una instancia de IPHostEnty que contiene una lista de direcciones y alias para el nombre solicitado. En la mayoría de los casos, puede utilizar la primera dirección devuelta en la matriz AddressList
. El siguiente código obtiene una instancia de IPAddress que contiene la dirección IP del servidor host.contoso.com.
IPHostEntry ipHostInfo = Dns.Resolve("host.contoso.com");
IPAddress ipAddress = ipHostInfo.AddressList[0]
También puedes; Utilice el método GetHostName para obtener una instancia de IPHostEntry:
IPHosntEntry hostInfo=Dns.GetHostByName("host.contoso.com")
Cuando utilice el método anterior, es posible que deba controlar la siguiente excepción:
SocketException: se produjo un error del sistema operativo al acceder al Socket.
ArgumentNullException: el parámetro es una referencia nula.
ObjectDisposedException: el Socket se ha cerrado.
Con el conocimiento anterior en la mano, el siguiente código combina la dirección IP del host del servidor (host.contoso.com
con un número de puerto para crear una conexión remota punto final para la conexión:
IPEndPoint ipe = new IPEndPoint(ipAddress, 11000);
Después de determinar la dirección del dispositivo remoto y seleccionar el puerto para la conexión, la aplicación puede intentarlo. para establecer una conexión con el dispositivo remoto
Conexión al dispositivo El siguiente ejemplo utiliza una instancia de IPEndPoint existente para conectarse al dispositivo remoto y detectar las excepciones que pueden
generarse:
try {
s.Connect(ipe); //Intenta conectar
}
//El parámetro de manejo es una referencia nula excepción
catch(ArgumentNullException ae) {
Console.WriteLine("ArgumentNullException: {0}", ae.ToString()
} ); p>
//Manejo de excepciones del sistema operativo
catch(SocketException se) {
Console.WriteLine("SocketException: {0}", se.ToString());
}
catch(Exception e) {
Console.WriteLine("Excepción inesperada: {0}", e.ToString()); p>
}
Obligatorio Lo que necesita saber: La clase Socket admite dos modos básicos: sincrónico y asincrónico.
La diferencia es que en el modo síncrono, las llamadas a funciones que realizan operaciones de red (como enviar y recibir) esperan hasta que se complete la operación antes de devolver el control al programa que realiza la llamada. En modo asíncrono, estas llamadas regresan inmediatamente.
Además, muchas veces, la programación de Socket debe implementarse en el cliente y el servidor respectivamente según la situación.
Compile una aplicación en el cliente para enviar una solicitud al lugar especificado. puerto en el servidor y, al mismo tiempo, prepare una aplicación de servidor para manejar la solicitud. Este proceso se ha mencionado en la descripción anterior, por supuesto, no toda la programación de Socket requiere que usted escriba estrictamente estos dos programas finales; Situación de la aplicación, puede construir una cadena de solicitud en el cliente y el puerto correspondiente del servidor capturará la solicitud y la entregará a su programa de servicio público para su procesamiento. La cadena en la siguiente declaración de ejemplo realiza una solicitud de página al host remoto:
string Get = "GET / HTTP/1.1\r\nHost: " server "\r\ nConnection: Close\r\n \r\n";
Después de que el puerto especificado del host remoto reciba esta solicitud, puede usar su programa de servicio público para procesarla sin la necesidad de
preparar un servidor separado. -aplicación lateral.
Utilizando el conocimiento mencionado anteriormente sobre el uso de Visual C# para desarrollar programas de red Socket, el siguiente programa
implementa completamente la función de descarga de páginas web. El usuario solo necesita ingresar el nombre del host remoto (nombre del host DNS o dirección IP en formato de notación de cuatro partes con puntos) y el nombre del archivo local previamente guardado en el formulario y usar el
>Puerto 80, que proporciona específicamente el servicio Http, puede obtener la página del host remoto y guardarla en el archivo especificado en la máquina local
. Si el formato para guardar es .htm, puede abrir la página en un navegador de Internet. Al agregar el código apropiado
puedes incluso implementar un programa de navegador simple.
El código fuente principal para implementar esta función es el siguiente:
//Evento del botón "Inicio"
botón de anulación privada1_Click(remitente del objeto, System.EventArgs e) {
//Obtener el nombre del archivo guardado previamente
string fileName=textBox3.Text.Trim()
//Host remoto
; p>string hostName=textBox1.Text.Trim();
//Puerto
int port=Int32.Parse(textBox2.Text.Trim()); /p>
//Obtener información del host
IPHostEntry ipInfo=Dns.GetHostByName(hostName
//Obtener dirección IP[]
DirecciónIP[); ] ipAddr=ipInfo .AddressList
//Obtener ip
IPAddress ip=ipAddr[0]
//Combinar el punto final remoto
;IPEndPoint hostEP=new IPEndPoint(ip, puerto);
//Crear instancia de Socket
Socket socket=new
Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
intenta
{
//Intenta conectar
socket.Connect(hostEP) ;
}
catch(Exception se)
{
MessageBox.Show("Error de conexión" se.Message, "Mensaje message
, MessageBoxButtons.RetryCancel, MessageBoxIcon.Information
}
//Solicitud de cadena de contenido enviada al host remoto
string sendStr=" GET/HTTP/1.1\r\nHost: "hostName
"\r\nConexión: Cerrar\r\n\r\n"; bytes byte array Convierte la cadena de envío
byte[] bytesSendStr=new byte[1024]
//Convierte la cadena de contenido de envío en una matriz de bytes
bytesSendStr =Encoding.ASCII.GetBytes(sendStr);
intenta
{
//Enviar una solicitud al socket del host
.Send( bytesSendStr, bytesSendStr.Length, 0
}
catch(Exception ce)
{
MessageBox.Show ("Error de envío: "ce.Message", mensaje emergente
, MessageBoxButtons.Re
tryCancel, MessageBoxIcon.Information);
}
//Indique la cadena para recibir el contenido devuelto
string recvStr=""; p >//Declara la matriz de bytes, la longitud de los datos recibidos a la vez es 1024 bytes
byte[] recvBytes=new byte[1024]
//Devuelve la palabra; del contenido recibido real Número de secciones
int bytes=0
//Leer en un bucle hasta que se reciban todos los datos
while(true)
{
bytes=socket.Receive(recvBytes, recvBytes.Length, 0),
//Salga del ciclo una vez completada la lectura
<); p>if(bytes〈= 0)break;
//Convierte el número de bytes leídos en una cadena
recvStr =Encoding.ASCII.GetString (recvBytes, 0, bytes);
}
//Convierte la cadena leída en una matriz de bytes
byte[] content=Encoding.ASCII.GetBytes ( recvStr);
prueba
{
//Crear una instancia de objeto de flujo de archivos
FileStream fs=new
FileStream(fileName, FileMode.OpenOrCreate, FileAccess.ReadWrite
//Escribir archivo
fs.Write(content, 0, content.Length
}
catch(Exception fe)
{
MessageBox.Show("Error de creación/escritura de archivo: " fe.Message", mensaje Información
", MessageBoxButtons.RetryCancel, MessageBoxIcon.Information);
}
//Desactivar socket
socket.Shutdown(SocketShutdown .Ambos);
//Cerrar socket
socket.Close()
}
}