يقوم برنامج المثال التالي بتطبيق اتصال مأخذ توصيل بسيط ويمكنه فتح عملاء متعددين. نجح الاختبار المحلي، ولكن لم يتم إجراء أي اختبار عبر الإنترنت.
الخادم:
باستخدام System.Net؛
باستخدام System.Net.Sockets؛
باستخدام
System.Threading؛
namespace MySocketServer1
{
public Partial class Form1 : Form
{
Private IPAddress serverIP = IPAddress.Parse("127.0.0.1");// استخدم هذا الجهاز للاختبار
الخاص IPEndPoint serverFullAddr;// عنوان المحطة الطرفية الكامل
Privateocket sock
; Timer myTimer;
Private ArrayList alSock;// يستخدم لحفظ الاتصالات عند إنشاء اتصالات متعددة
public Form1()
{
InitializeComponent()
;
Private void btStart_Click(object sender, EventArgs e)
{
serverFullAddr = new IPEndPoint(serverIP, 1000); // احصل على رقم المنفذ 1000
// أنشئ كائن المقبس، ونوع المقبس هو "مقبس الدفق"، حدد المجموعة الخمسة عنصر البروتوكول
sock = newocket(AddressFamily.InterNetwork, JackType.Stream,
ProtocolType.Tcp);
// حدد الثنائي المحليفي
المجموعة الخمسة، أي عنوان المضيف المحلي ورقم المنفذ
sock.Bind(serverFullAddr);
/Listen ما إذا كان هناك اتصال وارد، حدد الحد الأقصى لقيمة قائمة انتظار الاتصال المعلقة لتكون 20
sock.Listen(20);
alSock = new ArrayList();
// أنشئ مؤقتًا بفجوة زمنية مدتها ثانية واحدة، أي قم بتنفيذ طريقة Accept () كل ثانية للحصول على أول طلب اتصال معلق في قائمة انتظار طلبات الاتصال
myTimer =new System.Timers.Timer(1000 )
; المنقضي +=new System.Timers.ElapsedEventHandler(myTimer_Elapsed);
myTimer.Enabled = true
}
;
Private void myTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
myTimer.Enabled = false;
// تنفيذ قبول ()، سيتم حظر هذا الموضوع عندما تكون قائمة انتظار التعليق فارغة، وسيتوقف المؤقت بسبب العبارة السابقة ، حتى // حتى يتم تمرير الاتصال إلى
المقبس AcceptSock = sock.Accept();
// قمبتخزين
كائن المقبس الذي تم إنشاؤه بواسطة Accept() في ArrayList
alSock.Add(acceptSock);
مما سيؤدي إلى بدء البرنامج لموضوع آخر. سيقوم مؤشر الترابط بتنفيذ وظيفة رد الاتصال، ويجب أن تكون معلمات الدالة لحد المفوض من نوع الكائن. المعلمة الثانية لمنشئ 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)
{
المقبس AcceptSock = (Socket)obj;
حاول
{
while (true)
{
byte[]byteArray
= new byte[100]
; المصفوفة في
سلسلة strRec = System.Text.Encoding.UTF8.GetString(byteArray);
if (this.rtbReceive.InvocRequired)
{
this.rtbReceive.Invoc(new EventHandler(this.ChangeRickTextBox), new
object[] { strRec , EventArgs.Empty });
}
}
}
Catch(Exception ex)
{
AcceptSock.Close
(
)
;
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)
{
المقبس sc=null;
byteSend[] byteSend =
System.Text.Encoding.UTF8.GetBytes(this.tbSend.Text.ToCharArray
());
في نفس الوقت عندما يتصل العميل، أدخل الاتصال الذي سيتم إرساله في textBox1
int Index = int.Parse(this.textBox1.Text.Trim());
sc
=
(Socket)alSock[index - 1];
.Send(byteSend);
}
Catch(Exception ex)
{
if(sc != null)
{
sc.Close()
}
messageBox.Show("S:Send message Error"+ex.Message
)
;
Private void btClose_Click(object sender, EventArgs e)
{
try
{
Application.Exit
();
}
catch (Exception ex)
{
MessageBox.Show
("S:Close Connector Error" +
ex.Message
)
;
= == == == == == == == == == == == == == == == == == == == == = == == == ==
العميل:
استخدام System.Net؛
باستخدام System.Net.Sockets
؛
namespace MySocketClient1
{
public Partial class Form1: Form
{
PrivateIPAddress
serverIP = IPAddress.Parse("127.0.0.1")
;
public Form1()
{
InitializeComponent()
;
Private void btConnect_Click(object sender, EventArgs e)
{
try
{
serverFullAddr
= new IPEndPoint(serverIP, 1000
)
;
إنشاء اتصال بالمضيف البعيد
// ابدأ موضوعًا جديدًا لتلقي البيانات
Thread t = new Thread(new ThreadStart(ReceiveMsg));
t.Name = "Receive message";
// الخيط إما أن يكون خيطًا في الخلفية أو خيطًا في المقدمة. سلاسل الخلفية تشبه سلاسل الرسائل الأمامية، باستثناء أن سلاسل الخلفية // لا تمنع انتهاء العملية. بمجرد انتهاء جميع سلاسل العمليات الأمامية التي تنتمي إلى عملية ما، ينهي وقت تشغيل اللغة العامة // العملية عن طريق استدعاء "إحباط" على أي سلاسل عمليات في الخلفية لا تزال نشطة.
t.IsBackground = true;
t.Start();
}
catch(Exception ex)
{
MessageBox.Show
(ex.Message)
;
Private void ReceiveMsg()
{
try
{
while
(true)
{
byte[] byteRec = new byte[100];
this.sock.Receive(byteRec)
;
(this.rtbReceive.InspokeRequired)
{
this.rtbReceive.Invoc(new
EventHandler
(
ChangeRtb
), new object[]
{
strRec, EventArgs.Empty })
;
"+ex.Message);
}
}
Private void ChangeRtb(object obj, EventArgs e)
{
string s = System.Convert.ToString(obj);
this.rtbReceive.AppendText(s + Environment.NewLine })
;
Private void btSend_Click(object sender, EventArgs e)
{
byte
[
] byteSend =
System.Text.Encoding.UTF8.GetBytes
(
this.tbSend.Text.ToCharArray())
;
{
MessageBox.Show("خطأ في إرسال الرسالة"
)
;
Private void btClose_Click(object sender, EventArgs e)
{
try
{
this.sock.Shutdown(
SocketShutdown.Receive);
this.sock.Close
(
);
Application.Exit
();
}
}
}
}
اللغز
:
العبارة المميزة باللون الأحمر من جانب العميل: this.sock.Shutdown(SocketShutdown.Receive)، إذا تم تغييرها إلى
this.sock.Shutdown(SocketShutdown.Both); إرسال)؛
ثم عند النقر على زر الإغلاق، يرتفع استخدام وحدة المعالجة المركزية إلى 100%، ومع ذلك، فإن استخدام this.sock.Shutdown(SocketShutdown.Receive);
أو عدم استدعاء أسلوب Shutdown() لا يؤدي إلى حدوث هذه المشكلة. ألا يجب على العميل استخدام Shutdown()؟
http://www.cnblogs.com/KissKnife/archive/2006/08/13/475707.html