您的位置:首页 > 理论基础 > 计算机网络

基于C#的异步Socket程序(TCP)

2017-12-03 19:58 555 查看
今天我门将通过一个多人聊天的例子来说明异步Socket程序。

没有基础的可以看一下之前的同步Socket程序。

地址:http://blog.csdn.net/YongshuangZhao/article/details/78696718

1.代码如下:

服务端代码:

using System;
using System.Net;
using System.Net.Sockets;
using System.Collections;
using System.Collections.Generic;

namespace AsyncTCPServer
{
//客户端连接类
public class Connect
{
//与客户端连接的套接字
public Socket socket;
//缓冲区大小
public const int BUFFER_SIZE=1024;
//读缓冲区
public byte[] readBuff=new byte[BUFFER_SIZE];
//当前缓冲区大小
public int buffCount=0;
//是否被使用
public bool isUse=false;

public Connect ()
{
readBuff=new byte[BUFFER_SIZE];
}
//初始化
//初始化方法,在启用一个连接时会调用该方法,从而给一些变量赋值
public void Init(Socket socket){
this.socket = socket;
isUse = true;
buffCount = 0;
}
//缓冲区剩余的字节数
public int BuffRemain(){
return BUFFER_SIZE - buffCount;
}
//获取客户端IP地址和端口
public string GetAdress(){
if (!isUse) {
return "无法获取地址";
}
return socket.RemoteEndPoint.ToString ();
}
//关闭
public void Close(){
if (!isUse) {
return;
}
Console.WriteLine ("[断开连接]" + GetAdress ());
socket.Close ();
isUse = false;
}
}
}

using System;
using System.Net;
using System.Net.Sockets;
using System.Collections;
using System.Collections.Generic;

namespace AsyncTCPServer
{
//该类包含一个Connect类型的对象池(数组),用于维护客户端连接。
public class Server
{
//监听嵌套字
public Socket listenfd;
//客户端连接
public Connect[] connects;
//最大连接数
public int maxConnectCount=50;

//开启服务器
public void Start(string host,int port){
//连接池
connects=new Connect[maxConnectCount];
for (int i = 0; i < maxConnectCount; i++) {
connects [i] = new Connect ();
}
//Socket连接的流程
//socket
listenfd =new Socket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp);
//Bind
IPAddress ipAdr=IPAddress.Parse(host);
IPEndPoint ipEp = new IPEndPoint (ipAdr, port);
listenfd.Bind (ipEp);
//Listen
listenfd.Listen(maxConnectCount);
//Accept
listenfd.BeginAccept(AcceptCb,null);
Console.WriteLine ("[服务器]启动成功");
}
//获取连接池索引,返回负数表示获取失败
public int NewIndex(){
if (connects == null) {
return -1;
}
for (int i = 0; i < connects.Length; i++) {
if (connects [i] == null) {
connects [i] = new Connect ();
return i;
} else if (connects [i].isUse == false) {
return i;
}
}
return -1;
}
//Accept是BeginAccept的回调函数,它成立了如下3件事情
//(1)给新的连接分配connect
//(2)异步接收客户端数据
//(3)再次调用BeginAccept实现循环
//Accept回调
private void AcceptCb(IAsyncResult ar){
try{
Socket socket=listenfd.EndAccept(ar);
int index=NewIndex();

if(index<0){
socket.Close();
Console.WriteLine("[警告]连接已满");
}else{
Connect connect=connects[index];
connect.Init(socket);
string adr=connect.GetAdress();
Console.WriteLine("客户端["+adr+"]connect池ID:"+index);
connect.socket.BeginReceive(connect.readBuff,connect.buffCount,connect.BuffRemain(),SocketFlags.None,ReceiveCb,connect);
}
listenfd.BeginAccept(AcceptCb,null);
}catch(Exception e){
Console.WriteLine ("AcceptCb失败:" + e.Message);
}
}
//ReceiveCb是BeginReceive的回调函数,它处理了3件事情
//(1)接收并处理消息,因为有多个客户端,服务端收到消息后,要把它转发给所有人
//(2)如果收到客户端关闭连接的信号(count==0),则断开连接
//(3)继续调用BeginReceive接收下一个数据
//Receive回调
private void ReceiveCb(IAsyncResult ar){
Connect connect = (Connect)ar.AsyncState;
try{
int count=connect.socket.EndReceive(ar);
//关闭信号
if(count<=0){
Console.WriteLine("收到["+connect.GetAdress()+"]断开连接");
connect.Close();
return;
}
//数据处理
string str=System.Text.Encoding.UTF8.GetString(connect.readBuff,0,count);
Console.WriteLine("收到["+connect.GetAdress()+"]数据:"+str);
str=connect.GetAdre
a62b
ss()+":"+str;
byte[] bytes=System.Text.Encoding.Default.GetBytes(str);
//广播
for(int i=0;i<connects.Length;i++){
if(connects[i]==null){
continue;
}
if(!connects[i].isUse){
continue;
}
Console.WriteLine("将消息转播给"+connects[i].GetAdress());
connects[i].socket.Send(bytes);
}
//继续接收
connect.socket.BeginReceive(connect.readBuff,connect.buffCount,connect.BuffRemain(),SocketFlags.None,ReceiveCb,connect);
}catch(Exception e){
Console.WriteLine ("AcceptCb失败:" + e.Message);
Console.WriteLine ("收到[" + connect.GetAdress () + "]断开连接");
connect.Close ();
}
}
}
}
异步服务端示意图如下:



using System;
using System.Net;
using System.Net.Sockets;
using System.Collections;
using System.Collections.Generic;

namespace AsyncTCPServer
{
class MainClass
{
public static void Main (string[] args)
{
Server server = new Server ();
server.Start ("127.0.0.1",1234);
while (true) {
string str = Console.ReadLine ();
switch (str) {
case "quit":
return;
}
}
}
}
}
2.客户端代码如下:
using System;
using System.Net;
using System.Net.Sockets;

namespace AsyncTCPClient
{
public class Client
{
//Socket和接收缓存区
private Socket socket;
private byte[] readBuff;
private const int BUFFER_SIZE = 1024;

//启动客户端
public void Start(string host,int port){
//Socket
socket = new Socket (AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp);
//Connect
socket.Connect(host,port);
//Receive
readBuff=new byte[BUFFER_SIZE];
socket.BeginReceive (readBuff, 0, BUFFER_SIZE, SocketFlags.None, ReceiveCb, null);
}
//接收回调
private void ReceiveCb(IAsyncResult ar){
try {
//count是接收数据的大小
int count = socket.EndReceive (ar);
//数据处理
string str = System.Text.Encoding.UTF8.GetString (readBuff, 0, count);
Console.WriteLine(str);
//继续接收
socket.BeginReceive (readBuff, 0, BUFFER_SIZE, SocketFlags.None, ReceiveCb, null);
} catch (Exception e) {
Console.WriteLine (e.Message);
Console.WriteLine ("连接已断开");
socket.Close ();
}
}
//发送回调
public void Send(string str){
byte[] bytes = System.Text.Encoding.Default.GetBytes (str);
try {
socket.Send (bytes);
} catch {
}
}
}
}

using System;
using System.Net;
using System.Net.Sockets;

namespace AsyncTCPClient
{
class MainClass
{
public static void Main (string[] args)
{
Client client = new Client ();
client.Start ("127.0.0.1", 1234);
Console.ReadKey ();

while (true) {
string str = Console.ReadLine ();
if (str == "quit") {
return;
} else {
client.Send (str);
}
}
}
}
}
3.运行结果如下:

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: