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[转]的更多相关文章

  1. SQL Server数据库连接字符串的组成

    DB驱动程序常见的驱动程序如下: ODBC   ODBC(Open Database Connectivity,开放数据库互连)是微软公司开放服务结构(WOSA,Windows Open Servic ...

  2. 可扩展多线程异步Socket服务器框架EMTASS 2.0 续

    转载自Csdn:http://blog.csdn.net/hulihui/article/details/3158613 (原创文章,转载请注明来源:http://blog.csdn.net/huli ...

  3. Netty学习笔记

    一些类与方法说明 1)ByteBuf ByteBuf的API说明: Creation of a buffer It is recommended to create a new buffer usin ...

  4. 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 ...

  5. Node.js 进程平滑离场剖析

    本文由云+社区发表 作者:草小灰 使用 Node.js 搭建 HTTP Server 已是司空见惯的事.在生产环境中,Node 进程平滑重启直接关系到服务的可靠性,它的重要性不容我们忽视.既然是平滑重 ...

  6. 针对UDP丢包问题,进行系统层面和程序层面调优

    转自:https://blog.csdn.net/xingzheouc/article/details/49946191 1. UDP概念 用户数据报协议(英语:User Datagram Proto ...

  7. C# WinForm开发系列 - 文章索引

    该系列主要整理收集在使用C#开发WinForm应用文章及相关代码, 平时看到大家主要使用C#来开发Asp.Net应用,这方面的文章也特别多,而关于WinForm的文章相对少很多,而自己对WinForm ...

  8. 异步Socket服务器与客户端

      本文灵感来自Andre Azevedo 在CodeProject上面的一片文章,An Asynchronous Socket Server and Client,讲的是异步的Socket通信. S ...

  9. 学习笔记之JSON

    JSON https://www.json.org/ JSON (JavaScript Object Notation) is a lightweight data-interchange forma ...

随机推荐

  1. IDEA远程代码实时同步(可以自动实时同步)

    前言 开发时一般的平台都是windows,但windows对开发极其不友好,一般都会在本地开启虚拟机,安装上linux环境进行项目的部署测试.下面介绍一种windows主机与linux虚拟机代码同步的 ...

  2. 在Linux下将HTML文件转换成PDF文件

    今天要写一个上交的作业,本来是想用Office Word来写的,但是,我的Office貌似不能用了,但是,Linux下的LibreOffice写出的文档,在打印的时候是经常出现乱码的.所以,后来想到可 ...

  3. JavaScript原型&原型链

    原型&原型对象 先来一段简单的代码: function Fun(name) { this.name = name } var obj = new Fun('obj') JavaScript中的 ...

  4. oracel分页查询

    SELECT * FROM ( SELECT temp.*, ROWNUM RN FROM (SELECT * FROM 表名) temp WHERE ROWNUM <=end (page*pa ...

  5. linux设置python虚拟环境的环境变量

    针对 linux系统中 python虚拟环境 设置环境变量 2种方法: 1.在建好的虚拟环境的 venv/bin/active 文件中,写入需要的环境变量,再进入虚拟环境: 如 配置文件路径 JERR ...

  6. 四、附加到进程调试(.NET Core)

    1.安装.net core windows server托管工具包: 1.下载https://dotnet.microsoft.com/download/thank-you/dotnet-runtim ...

  7. Codeforces 633F 树的直径/树形DP

    题意:有两个小孩玩游戏,每个小孩可以选择一个起始点,并且下一个选择的点必须和自己选择的上一个点相邻,问两个选的点权和的最大值是多少? 思路:首先这个问题可以转化为求树上两不相交路径的点权和的最大值,对 ...

  8. AES apache commons-crypto 对称加密

    apache实现的AES256加密 官方用户指导链接:http://commons.apache.org/proper/commons-crypto/userguide.html 官方字节缓存实现的例 ...

  9. 一、Spring Boot系列:通过Maven创建第一个项目

    1.打开idea选择创建工程 2.创建maven工程,同时选择jdk1.8 注意:不需要勾选其他选项 3.填写项目名称 4.创建好maven项目后,在pom.xml文件中导入Spring Boot需要 ...

  10. java 方法返回多个值

    package java03; /* * 一个方法可以有0,1或者多个参数,但是返回值只能有0或者1个返回值,不能有多个返回值 * 但是如果希望有多个返回值,应该怎么办? * 答:使用数组作为返回值类 ...