O programa de exemplo a seguir implementa comunicação simples de Socket e pode abrir vários clientes. O teste local passou, mas nenhum teste online foi feito.
Servidor:
usando System.Net;
usando
System.Net.Sockets
;
namespace MySocketServer1
{
public parcial class Form1 : Form
{
private IPAddress serverIP = IPAddress.Parse("127.0.0.1");//Use esta máquina para testar
IPEndPoint privado serverFullAddr;//Endereço de terminal completo
private Socket sock
; Timer myTimer;
private ArrayList alSock;//Usado para salvar conexões quando múltiplas conexões são estabelecidas
public Form1()
{
InicializarComponent()
;
private void btStart_Click(object sender, EventArgs e)
{
serverFullAddr = new IPEndPoint(serverIP, 1000); //Obtém o número da porta 1000
//Constrói o objeto Socket, o tipo de soquete é "stream socket", especifica a tupla de cinco. elemento de protocolo
sock = new Socket(AddressFamily.InterNetwork, SocketType.Stream,
ProtocolType.Tcp);
//Especifique o binário local na tupla de cinco, ou seja, o endereço do host local e o número da porta
sock.Bind(serverFullAddr /)
; /Listen Se houver uma conexão de entrada, especifique o valor máximo da fila de conexões pendentes como 20
sock.Listen(20);
alSock = new ArrayList();
//Construa um timer com intervalo de tempo de 1 segundo, ou seja, execute o método accept() a cada segundo para obter a primeira solicitação de conexão pendente na fila de solicitações de conexão
myTimer =new System.Timers.Timer(1000 )
; Decorrido +=new System.Timers.ElapsedEventHandler(myTimer_Elapsed
)
;
private void myTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
myTimer.Enabled = false;
//Execute accept(), este thread será bloqueado quando a fila de suspensão estiver vazia e o cronômetro irá parar devido à instrução anterior , até // até que uma conexão seja passada para
o Socket acceptSock = sock.Accept();
//Armazene
o objeto Socket gerado por accept() no ArrayList
alSock.Add(acceptSock);
o que fará com que o programa inicie outro thread. O thread executará a função de retorno de chamada e os parâmetros de //função de limite delegado devem ser do tipo de objeto. O segundo parâmetro do construtor Threading.Timer é o parâmetro passado para a função de retorno de chamada; //O terceiro parâmetro especifica o atraso antes de chamar a função de retorno de chamada, se for 0, ele iniciará imediatamente; a função de retorno de chamada // Intervalo, se definido como 0, será executado apenas uma vez.
System.Threading.Timer ti = novo System.Threading.Timer(new
TimerCallback(ReceiveMsg)
,acceptSock
, 0, 0);
private void ReceiveMsg(object obj)
{
Socket acceptSock = (Socket)obj;
try
{
while (true)
{
byte[] byteArray = new byte[100];
//Receber dados
//Converter byte Converter a matriz em uma
string strRec = System.Text.Encoding.UTF8.GetString(byteArray);
if (this.rtbReceive.InvokeRequired)
{
this.rtbReceive.Invoke(new EventHandler(this.ChangeRickTextBox), new
object[] { strRec ,
EventArgs.Empty
} }
}
}
catch
(Exceção ex)
{
acceptSock.Close(
)
;
private void ChangeRickTextBox(objeto obj,EventArgs e)
{
string s = System.Convert.ToString(obj);
this.rtbReceive.AppendText(s + Environment.NewLine })
;
private void btSend_Click(object sender, EventArgs e)
{
Socket
sc=
null;
byteSend =
System.Text.Encoding.UTF8.GetBytes(this.tbSend.Text.ToCharArray
());
ao mesmo tempo Quando o cliente se conectar, insira qual conexão enviar em textBox1
int index=
int.Parse(this.textBox1.Text.Trim()
)
;
.Send(byteSend);
}
catch(Exceção ex)
{
if(
sc != null)
{
sc.Close
(
)
;
private void btClose_Click(objeto remetente, EventArgs e)
{
try
{
Application.Exit(
)
}
catch(
Exceção ex)
{
MessageBox.Show
("S:Erro de fechamento de soquete" + ex.Message
)
;
= == == == == == == == == == == == == == == == == == == == == == == == = = = = == == == ==
Cliente:
usando System.Net;
usando
System.Net.Sockets
;
namespace MySocketClient1
{
classe parcial pública Form1: Formulário
{
private IPAddress serverIP = IPAddress.Parse("127.0.0.1");
private IPEndPoint serverFullAddr
private Socket sock;
public Form1()
{
InicializarComponent()
;
private void btConnect_Click (objeto remetente, EventArgs e)
{
tente
{
serverFullAddr=
new IPEndPoint (serverIP, 1000
)
;
Estabeleça uma conexão com o host remoto
//Iniciar um novo thread para receber dados
Thread t = new Thread(new ThreadStart(ReceiveMsg));
t.Name = "Receive Message";
//Um thread é um thread de segundo plano ou um thread de primeiro plano. Threads de segundo plano são semelhantes aos threads de primeiro plano, exceto que o thread de segundo plano // não impede o encerramento do processo. Depois que todos os encadeamentos em primeiro plano pertencentes a um processo forem encerrados, o Common Language Runtime // encerra o processo chamando Abort em quaisquer encadeamentos em segundo plano que ainda estejam ativos.
t.IsBackground
=
true
;
t.Start
(
)
;
private void ReceiveMsg()
{
try
{
while
(true)
{
byte[] byteRec = new byte[100
]
;
(this.rtbReceive.InvokeRequired)
{
this.rtbReceive.Invoke(new EventHandler(ChangeRtb), new object[]
{ strRec, EventArgs.Empty }
}
catch(Exception ex)
{
MessageBox.Show("Erro de recebimento de mensagem"
)
;
"+ex.Mensagem);
}
}
private void ChangeRtb(objeto obj, EventArgs e)
{
string s = System.Convert.ToString(obj);
this.rtbReceive.AppendText(s + Environment.NewLine })
;
private void btSend_Click (objeto remetente, EventArgs e)
{
byte
[
] byteSend =
System.Text.Encoding.UTF8.GetBytes
(
this.tbSend.Text.ToCharArray())
;
{
MessageBox.Show
("Erro ao enviar mensagem")
;
private void btClose_Click (
objeto
remetente, EventArgs e)
{
tente
{
this.sock.Shutdown (SocketShutdown.Receive);
this.sock.Close
(
)
Application.Exit
();
;
} }
}
}
Quebra-cabeça
:
A instrução marcada em vermelho no lado do cliente: this.sock.Shutdown(SocketShutdown.Receive), se alterado para
this.sock.Shutdown(SocketShutdown.Both); Send);
então, quando o botão Fechar é clicado, o uso da CPU dispara para 100%. No entanto, usar this.sock.Shutdown(SocketShutdown.Receive)
; O cliente não deveria usar Shutdown()?
http://www.cnblogs.com/KissKnife/archive/2006/08/13/475707.html