Следующий пример программы реализует простую связь через Socket и может открывать несколько клиентов. Локальный тест пройден, но онлайн-тест не проводился.
Сервер:
использование System.Net;
использование System.Net.Sockets;
использование
System.Threading
;
пространство имен MySocketServer1
{
public parts class Form1 : Form
{
Private IPAddress serverIP = IPAddress.Parse("127.0.0.1");//Используйте эту машину для тестирования
частного IPEndPoint serverFullAddr;//Полный адрес терминала
Private Socket
Private System.Timers. Таймер myTimer;
частный ArrayList alSock;//Используется для сохранения соединений, когда установлено несколько соединений.
общественная форма1 ()
{
InitializeComponent ()
}
;
Private void btStart_Click(object sender, EventArgs e)
{
serverFullAddr = new IPEndPoint(serverIP, 1000); //Получаем номер порта 1000
//Создаем объект Socket, тип сокета — «потоковый сокет», указываем кортеж из пяти элемент протокола
sock = new Socket(AddressFamily.InterNetwork, SocketType.Stream,
ProtocolType.Tcp
//Укажите локальный двоичный файл в пятерке, то есть адрес локального хоста и номер порта
sock.Bind(serverFullAddr);
/ /Listen Если есть входящее соединение, укажите максимальное значение очереди ожидающих соединений, равное 20
sock.Listen(20);
alSock = новый ArrayList();
//Создаем таймер с интервалом в 1 секунду, то есть выполняем метод Accept() каждую секунду, чтобы получить первый ожидающий запрос на соединение в очереди запросов на соединение
myTimer =new System.Timers.Timer(1000 )
; Прошло + = новый System.Timers.ElapsedEventHandler(myTimer_Elapsed)
myTimer.Enabled = true
}
;
Private void myTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
myTimer.Enabled = false;
//Выполнить Accept(), этот поток будет заблокирован, когда очередь приостановки пуста, и таймер остановится из-за предыдущего оператора , // пока соединение не будет передано в
Socket AcceptSock = sock.Accept()
// Сохраняем объект Socket, сгенерированный функцией Accept(), в ArrayList
alSock.Add(acceptSock);
// Создаем объект Threading.Timer, что заставит программу запустить другой поток. Поток выполнит функцию обратного вызова, а параметры функции ограничения делегата должны иметь тип объекта. Второй параметр конструктора Threading.Timer — это параметр, передаваемый в функцию обратного вызова; //Третий параметр определяет задержку перед вызовом функции обратного вызова. Если он равен 0, последний параметр задает время вызова; функция обратного вызова // Интервал, если установлено значение 0, она будет выполнена только один раз.
System.Threading.Timer ti = new System.Threading.Timer(new
TimerCallback(ReceiveMsg), AcceptSock, 0, 0);
myTimer.Enabled = true
}
;
Private void ReceiveMsg(object obj)
{
Socket AcceptSock = (Socket)obj;
try
{
while (true)
{
byte[] byteArray = new byte[100];
//Получаем данные
//Преобразовать байт Convert массив в
строку strRec = System.Text.Encoding.UTF8.GetString(byteArray);
if (this.rtbReceive.InvokeRequired)
{
this.rtbReceive.Invoke(new EventHandler(this.ChangeRickTextBox), новый
объект[] { strRec , EventArgs.Empty });
}
}
}
catch(Exception ex)
{
AcceptSock.Close().
Show("S:Ошибка получения сообщения"+ex.Message }
}
;
Private void ChangeRickTextBox(object 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;
byte[] byteSend =
System.Text.Encoding.UTF8.GetBytes(this.tbSend.Text.ToCharArray
());
в то же время, когда клиент подключается, введите, какое соединение отправлять в textBox1
int index = int.Parse(this.textBox1.Text.Trim());
sc = (Socket)alSock[index - 1];
//Отправляем данные
sc; .Send(byteSend);
}
catch(Exception ex)
{
if(sc != null)
{
sc.Close()
}
MessageBox.Show("S:Ошибка отправки сообщения"+ex.Message
}
)
;
Private void btClose_Click(отправитель объекта, EventArgs e)
{
try
{
Application.Exit();
}
catch
(Exception ex)
{
MessageBox.Show
("S:Close Socket Error" +
ex.Message
)
;
= == == == == == == == == == == == == == == == == == == == == == == == = = = = == == == ==
Клиент:
использование System.Net;
использование System.Net.Sockets;
использование System.Threading;
пространство имен MySocketClient1
{
общественный частичный класс Form1: Форма
{
частный IPAddress serverIP = IPAddress.Parse("127.0.0.1");
частный IPEndPoint serverFullAddr;
частный Socket Socket;
общественная форма1 ()
{
InitializeComponent ()
}
;
Private void btConnect_Click(отправитель объекта, EventArgs e)
{
try
{
serverFullAddr = new IPEndPoint(serverIP, 1000);
sock = new Socket(AddressFamily.InterNetwork, SocketType.Stream,
ProtocolType.Tcp); //
sock.Connect(serverFullAddr);// Установить соединение с удаленным хостом
//Запускаем новый поток для получения данных
Thread t = new Thread(new ThreadStart(ReceiveMsg));
t.Name = "Receive Message";
//Поток может быть либо фоновым, либо приоритетным. Фоновые потоки аналогичны потокам переднего плана, за исключением того, что фоновый поток // не препятствует завершению процесса. Как только все потоки переднего плана, принадлежащие процессу, завершаются, среда CLR завершает // процесс, вызывая Abort для всех фоновых потоков, которые все еще активны.
t.IsBackground = true;
t.Start();
}
catch(Exception ex)
{
MessageBox.Show(ex.Message }
)
;
Private void ReceiveMsg()
{
try
{
while
(true)
{
byte[] byteRec = новый byte[100];
this.sock.Receive(byteRec);
строка strRec = System.Text.Encoding.UTF8.GetString(byteRec);
(this.rtbReceive.InvokeRequired)
{
this.rtbReceive.Invoke(new EventHandler(ChangeRtb)
, новый объект[]
{
strRec, EventArgs.Empty });
catch
(Exception ex)
{
MessageBox.Show("Ошибка получения сообщения
)"+ex.Сообщение);
}
}
Private void ChangeRtb(object obj, EventArgs e)
{
string s = System.Convert.ToString(obj);
this.rtbReceive.AppendText(s + Environment.NewLine })
;
частный void btSend_Click(отправитель объекта, EventArgs e)
{
byte[] byteSend =
System.Text.Encoding.UTF8.GetBytes(this.tbSend.Text.ToCharArray());
try
{
this.sock.Send(byteSend }
catch
)
;{
MessageBox.Show("Ошибка отправки сообщения"
}
}
Private void btClose_Click(отправитель объекта, EventArgs e)
{
try
{
this.sock.Shutdown(SocketShutdown.Receive);
this.sock.Close();
Application.Exit()
;
catch
{
MessageBox.Show("Ошибка выхода") ;
} }
}
}
Головоломка
:
отмеченный красным оператор на стороне клиента: this.sock.Shutdown(SocketShutdown.Receive), если он изменен на
this.sock.Shutdown(SocketShutdown.Both); или this.sock.Shutdown(SocketShutdown. Отправить);
затем при нажатии кнопки «Закрыть» загрузка ЦП резко возрастает до 100%. Однако использование this.sock.Shutdown(SocketShutdown.Receive);
или отсутствие вызова метода Shutdown() не приводит к этой проблеме. Разве клиент не должен использовать Shutdown()?
http://www.cnblogs.com/KissKnife/archive/2006/08/13/475707.html