Socket編程--同步的應用

小咪咪 2022-08-25 08:34 271阅读 0赞

同步編程使用的情況不多,在以下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

发表评论

表情:
评论列表 (有 0 条评论,271人围观)

还没有评论,来说两句吧...

相关阅读

    相关 C#組件(2)

    C\組件編程(2) 較复雜的屬性為了編輯方便,就要用到屬性編輯器. 由于在屬性視窗中只能識別字符串類型,如果是非字符串類型的屬性還需要用到類型轉換器. 下面就分別講它

    相关 Socket--同步

    同步編程使用的情況不多,在以下3種情況下可以使用同步: 1.客戶端數量較少情況下的服務端編程 2.客戶端數量較多,但都是短連接情況下的服務端編程 3.客戶端編程

    相关 [转]Oracle SQL 日期

    oracle SQL裡常用的時間函數,經典推薦 相信很多人都有過統計某些數據的經歷,比如,要統計財務的情況,可能要按每年,每季度,每月,甚至每個星期來分別統計。 那在ora