同步編程使用的情況不多,在以下3種情況下可以使用同步:
1.客戶端數量較少情況下的服務端編程
2.客戶端數量較多,但都是短連接情況下的服務端編程
3.客戶端編程
以下主要針對服務端編程的2種情況,分別做一示例,以下示例均使用tcp協議.
1.在客戶端數量較少的情況下,
数量较少是指会同时连接到服务器的客户端数量一般在50人以下。这种情况下我们可以考虑使用同步Socket+Thread来实现我们的服务端。这样会让我们编写逻辑更清晰的代码而性能不会下降太多。
首先创建一个Socket,并且给它绑定一个EndPoint后开始监听。接下来我们创建一个线程,在这个线程中我们用一个无限循环来接收来自客户端的连接请求。在接收到一个请求后,为这个客户端创建一个新的线程,并且在这个线程中也使用一个无限循环接收来自这个客户端的数据
private Socket listener;
private
void
button1_Click(
object
sender, EventArgs e)
{
//
建立socket偵聽連接
listener
=
new
Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
IPEndPoint locEP
=
new
IPEndPoint(IPAddress.Any,
2000
);
listener.Bind(locEP);
listener.Listen(
100
);
//
建立一個線程處理連接請求
Thread acceptThread
=
new
Thread(
new
ThreadStart(AcceptWorkThread));
acceptThread.Start();
}
//
處理連接請求函數
private
void
AcceptWorkThread()
{
Thread.CurrentThread.IsBackground
=
true
;
while
(
true
)
{
Socket accept
=
listener.Accept();
IPEndPoint remoEP
=
(IPEndPoint)accept.RemoteEndPoint;
//
string recString = "接收到来自" + remoEP.Address.ToString() + "的连接。";
//
this.Invoke(new AddListItemHandler(this.AddListItem), new string[] { recString });
//
為客戶端請求建立新的線程
Thread receiveThread
=
new
Thread(
new
ParameterizedThreadStart(ReceiveWorkThread));
receiveThread.Start(accept);
}
}
//
接收數據
private
void
ReceiveWorkThread(
object
obj)
{
Thread.CurrentThread.IsBackground
=
true
;
Socket socket
=
(Socket)obj;
byte
[] buffer
=
new
byte
[
1024
];
while
(
true
)
{
int
receiveCount
=
socket.Receive(buffer);
if
(receiveCount
>
0
)
{
IPEndPoint remoEP
=
(IPEndPoint)socket.RemoteEndPoint;
//
string recString = "来自客户端" + remoEP.Address.ToString() + "的消息:" + Encoding.Default.GetString(buffer, 0, receiveCount);
//
this.Invoke(new AddListItemHandler(this.AddListItem), new string[] { recString });
socket.Send(buffer, receiveCount, SocketFlags.None);
}
else
{
socket.Close();
break
;
}
}
}
2.客戶端數量較多,但都是短連接的情況下,
短连接是指客户端的连接在处理完一次收发之后就产即断开的场景,比如说HTTP协议就是一种短连接。HTTP在客户端发出请求时建立一个Socket连接,并通过Socket发出一个URL请求,服务端在处理完这个请求并回发相应的页面后便会断开这个连接。那么在这种场景下我们也可以使用同步Socket来实现我们的需求。
以下示例方案中每一个连接都是短连接。而且顺序都是固定的。都是:接入->接收->发送这样的顺序,那么我们就可以在一个方法中完成整个处理.
首先我们创建了一个Socket用于侦听客户端的连接请求,接下我们创建了一个拥有30个线程的线程池。并在每个线程中实现了Accept、Receive、Send和Close(),以完成连接、接收、发送、关闭的操作。
private Socket listener;
private
void
button1_Click(
object
sender, EventArgs e)
{
//
建立socket偵聽連接
listener
=
new
Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
IPEndPoint locEP
=
new
IPEndPoint(IPAddress.Any,
2000
);
listener.Bind(locEP);
listener.Listen(
100
);
//
建立一個線程池
Thread[] ClientThreadList
=
new
Thread[
30
];
for
(
int
i
=
0
; i
<=
30
; i
++
)
{
ClientThreadList[i]
=
new
Thread(
new
ThreadStart(ClientWorkThread));
ClientThreadList[i].Start();
}
}
//
處理連接請求
private
void
ClientWorkThread()
{
byte
[] buffer
=
new
byte
[
1024
];
while
(
true
)
{
Socket socket
=
listener.Accept();
//
string recString = "接收到来自" + remoEP.Address.ToString() + "的连接。";
//
this.Invoke(new AddListItemHandler(this.AddListItem), new string[] { recString });
int
receCount
=
socket.Receive(buffer);
if
(receCount
>
0
)
{
//
string recString = "来自客户端" + remoEP.Address.ToString() + "的消息:" + Encoding.Default.GetString(buffer, 0, receiveCount);
//
this.Invoke(new AddListItemHandler(this.AddListItem), new string[] { recString });
socket.Send(buffer, receCount, SocketFlags.None);
}
socket.Shutdown(SocketShutdown.Both);
socket.Close();
}
}
說明:本文是根據下面的鏈接改寫的,可以說是本人的理解思路.算做筆記吧.
參考文獻: 1. http://www.cnblogs.com/wzd24/archive/2007/05/21/753709.html