Asynchronous C# server[转]
It hasn't been thoroughly tested, but seems to work OK.
This should scale pretty nicely as well. Originally I was going to code it in C++, but after doing some research the scalability factor that I thought was going to gain using C++ seemed to be low considering the amount of work it was going to take.
Server.cs
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Net.Sockets;
using System.Net; namespace Server
{ public class Server
{
private int port;
private Socket serversocket; public delegate void ConnectionEvent(Connection conn);
public List<Connection> connections;
public event ConnectionEvent AcceptCallback;
public event ConnectionEvent RecieveCallback;
public event ConnectionEvent DisconnectCallback; public Server(int p)
{
port = p;
connections = new List<Connection>();
} public bool Start()
{
IPEndPoint ipendpoint; try
{ //do not assign an IP, as it is a server (IPAdress.Any)
ipendpoint = new IPEndPoint(IPAddress.Any, this.port); }
catch (ArgumentOutOfRangeException e)
{
//port was probably out of range
throw new ArgumentOutOfRangeException("Please check port number.", e); } try
{ //create the main server worker socket
serversocket = new Socket(ipendpoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp); }
catch (SocketException e)
{ //here because we couldn't create server socket
throw new ApplicationException("Couldn't create server socket.", e); } try
{
//bind the socket to the specified port
serversocket.Bind(ipendpoint); //begin listening for incoming connections
serversocket.Listen(); }
catch (SocketException e)
{ //probably here due to the port being in use
throw new ApplicationException("Couldn't bind/listen on port: " + this.port.ToString(), e); } try
{ //begin accepting incoming connections
serversocket.BeginAccept(new AsyncCallback(acceptCallback), this.serversocket); }
catch (Exception e)
{ throw new ApplicationException("Error assigning the accept callback.", e); } return true;
} private void acceptCallback(IAsyncResult ar)
{
Connection conn = new Connection(); try
{ //finish the connection //get the resulting state object
Socket sck = (Socket)ar.AsyncState; //create new connection object to be added to our concurrent connection list
conn = new Connection(sck.EndAccept(ar)); //lock our list for thread safety
lock(connections)
{ //add to our list
connections.Add(conn); } //begin accepting data on that socket, using our Connection object as the object state
conn.socket.BeginReceive(conn.buffer, , conn.buffer.Length, SocketFlags.None, new AsyncCallback(receiveCallback), conn); //start accepting connections again
serversocket.BeginAccept(new AsyncCallback(acceptCallback), this.serversocket); //if the eventhandler for incoming connections has been assgined, call it
if(AcceptCallback != null)
{ AcceptCallback(conn); } }
catch(SocketException e)
{
Disconnect(conn);
throw new ApplicationException(e.Message, e);
}
} private void Disconnect(Connection conn)
{
//remove connection from list
lock (connections)
{
connections.Remove(conn);
} //make sure it's completely closed
conn.socket.Close(); //if the eventhandler for disconnection has been assgined, call it
if (DisconnectCallback != null)
{ DisconnectCallback(conn); }
} private void receiveCallback(IAsyncResult ar)
{ //retrieve the connection that has data ready
Connection conn = (Connection)ar.AsyncState; try
{ //retrieve the data(bytes) while also returning how many bytes were read
int bytes = conn.socket.EndReceive(ar); //if bytes is more than zero, then data was successfully read
if(bytes > )
{ //if the data receive callback has been assigned, call it
if(RecieveCallback != null)
{ RecieveCallback(conn); } //being receiving data again
conn.socket.BeginReceive(conn.buffer, , conn.buffer.Length, SocketFlags.None, new AsyncCallback(receiveCallback), conn); }
else
{ //if zero bytes were read, connection was closed
Disconnect(conn); }
}
catch(SocketException e)
{ Disconnect(conn);
throw new ApplicationException("Error with EndReceive or BeginReceive", e);
}
}
}
}
Connection.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Net.Sockets; namespace Server
{ public class Connection
{
public byte[] buffer;
public Socket socket; public Connection()
{ }
public Connection(Socket sock)
{
buffer = new byte[];
socket = sock;
} public void Send(string data)
{
try
{ if (this.socket.Connected)
{
//convert string into an aray of bytes
byte[] buffer = ASCIIEncoding.ASCII.GetBytes(data); //send our byte[] buffer
socket.Send(buffer, SocketFlags.None);
} }
catch (SocketException e)
{
throw new ApplicationException("Error with Send", e);
}
} }
}
Usage:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Threading; namespace Server
{
class Program
{
static void Main(string[] args)
{
//port 80(webserver)
Server server = new Server( ); server.RecieveCallback += server_RecieveCallback;
server.AcceptCallback += server_AcceptCallback;
server.DisconnectCallback += server_DisconnectCallback;
server.Start(); ThreadStart threadstart = new ThreadStart(ThreadJob);
Thread thread = new Thread(threadstart); thread.Start(); } static void server_DisconnectCallback(Connection conn)
{
Console.WriteLine("Connection disconnected\n");
} static void server_AcceptCallback(Connection conn)
{
Console.WriteLine("Incoming connection\n");
} static void ThreadJob()
{
while (true)
Thread.Sleep();
} static void server_RecieveCallback(Connection conn)
{ Console.WriteLine(ASCIIEncoding.ASCII.GetString(conn.buffer)); }
}
}
Go to your web browser and type 127.0.0.1 into the address bar.
If any one sees any issues and things to improve on, let me know. (Sure there is).
If any one has any questions let me know.
Asynchronous C# server[转]的更多相关文章
- SQL Server数据库连接字符串的组成
DB驱动程序常见的驱动程序如下: ODBC ODBC(Open Database Connectivity,开放数据库互连)是微软公司开放服务结构(WOSA,Windows Open Servic ...
- 可扩展多线程异步Socket服务器框架EMTASS 2.0 续
转载自Csdn:http://blog.csdn.net/hulihui/article/details/3158613 (原创文章,转载请注明来源:http://blog.csdn.net/huli ...
- Netty学习笔记
一些类与方法说明 1)ByteBuf ByteBuf的API说明: Creation of a buffer It is recommended to create a new buffer usin ...
- Best packages for data manipulation in R
dplyr and data.table are amazing packages that make data manipulation in R fun. Both packages have t ...
- Node.js 进程平滑离场剖析
本文由云+社区发表 作者:草小灰 使用 Node.js 搭建 HTTP Server 已是司空见惯的事.在生产环境中,Node 进程平滑重启直接关系到服务的可靠性,它的重要性不容我们忽视.既然是平滑重 ...
- 针对UDP丢包问题,进行系统层面和程序层面调优
转自:https://blog.csdn.net/xingzheouc/article/details/49946191 1. UDP概念 用户数据报协议(英语:User Datagram Proto ...
- C# WinForm开发系列 - 文章索引
该系列主要整理收集在使用C#开发WinForm应用文章及相关代码, 平时看到大家主要使用C#来开发Asp.Net应用,这方面的文章也特别多,而关于WinForm的文章相对少很多,而自己对WinForm ...
- 异步Socket服务器与客户端
本文灵感来自Andre Azevedo 在CodeProject上面的一片文章,An Asynchronous Socket Server and Client,讲的是异步的Socket通信. S ...
- 学习笔记之JSON
JSON https://www.json.org/ JSON (JavaScript Object Notation) is a lightweight data-interchange forma ...
随机推荐
- P2172 [国家集训队]部落战争(最小路径覆盖)
P2172 [国家集训队]部落战争 每个点仅走一次:最小路径覆盖 套路地拆点,具体看代码中的$draw()$ 流量每增加1,意味着一支军队可以多走一格,代价减少1 最后答案即为总点数$-dinic() ...
- 修改 IIS 默认文件上传大小
IIS 7 默认文件上传大小是30M 要突破这个限制: 修改IIS的applicationhost.config 打开 c:/windows/system32/inetsrv/config/appli ...
- 手模手配置Eslint,看懂脚手架中的Eslint
使用ESLint前:eslint是干嘛的,我这样写有什么问题,怎么还报错了,太麻烦想去掉这个插件,脚手架中关于eslint文件里的配置是什么意思?怎么设置配置项和规则达到自己想要的检测效果呢?怎么集成 ...
- linux设置python虚拟环境的环境变量
针对 linux系统中 python虚拟环境 设置环境变量 2种方法: 1.在建好的虚拟环境的 venv/bin/active 文件中,写入需要的环境变量,再进入虚拟环境: 如 配置文件路径 JERR ...
- Git --05 Gitlab使用
目录 Gitlab使用 01. 外观配置 02. Gitlab汉化配置 03. 注册限制 04. 创建用户及组 05. 创建用户 06. 把用户添加到组 07. 创建项目 08. 推送代码到Gitla ...
- Zabbix学习笔记(yum源安装)
Zabbix学习笔记(yum源安装) 链接:https://pan.baidu.com/s/19RXhumkB-ulpI4BGOa5b_A 提取码:115h 复制这段内容后打开百度网盘手机App,操作 ...
- VS基本教程
首先打开vs,点击工具栏,文件----新建----项目 然后依次选择Visual C++----空项目-----命名---项目存放路径 接下来在解决方案资源管理器中选中源文件,右键----添加---- ...
- htmlunit填坑
htmlunit 无头浏览器 爬虫使用填坑: <!-- htmlunit start --> <dependency> <groupId>org.jsoup< ...
- office2016pro专业版命令行激活
1.首先查看Office2016安装目录在哪里,如果是默认安装,没有修改路径,是在C:\Program Files\Microsoft Office\Office16目录下,具体路径还得自行查看,我的 ...
- cmd退出python
cmd中如何退出Python (1)在命令行上输入exit() (2)在命令行上输入quit() (3)ctrl+Z 然后回车