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 ...
随机推荐
- 个人珍藏的PC和安卓应用列表
个人珍藏的PC和安卓应用列表 PC应用名称 功能描述 注意事项 存储位置 维棠FLV视频下载软件 可用来下载腾讯视频的视频 将视频列表的网址粘贴到维棠软件左侧"下载"的地址中即可批 ...
- ECG 项目预研
1. 数据的采集 智能安全帽,流数据,鉴于数据量大,应该是采集到云平台上,然后在云平台上对数据处理,是一种典型的物联网+大数据应用场景,考虑使用AWS或者阿里云,然后搭建Hadoop/Spark 环境 ...
- ELK日志分析系统之logstash7.x最新版安装与配置
2 .Logstash的简介 2.1 logstash 介绍 LogStash由JRuby语言编写,基于消息(message-based)的简单架构,并运行在Java虚拟机(JVM)上.不同于分离的代 ...
- 严重: StandardWrapper.Throwable org.springframework.beans.factory.BeanCreationException: Error creating bean with name
HTTP Status 500 - Servlet.init() for servlet mybatis threw exception type Exception report message S ...
- jvm(1)性能监控-linux相关命令
top命令能够实时显示系统中各个进程的资源占用情况,其输出信息分为两部分,前半部分为系统统计信息,后半部分是进程信息. 第一行是任务队列信息,它的结果等同于uptime命令. 第二行是进程统计信息: ...
- 分析abex'crackme#1
测试文件下载:https://www.wocloud.com.cn/webclient/share/sindex.action?id=i9K_Br6TgE7Kf_YTF04yHmKcRy5TUdZ8U ...
- Iplimage versus Mat
我们可能经常面临这样的困惑,Iplimage和Mat这两种数据结构,我们应该用哪一种数据结构. Iplimage一开始就存在opencv库之中,他来源于Intel的另外一个函数库Intel Image ...
- smbrun - smbd和外部程序间的接口程序。
总览 SYNOPSIS smbrun shell-command 描述 DESCRIPTION 此程序是samba套件的一部分. smbrun是个非常小的“粘合”程序,用于为smbd守护程序smbd( ...
- MySQL--07 explain用法
目录 MySQL explain用法 一.explain命令应用 二. Extra(扩展) 三.建立索引的原则(规范) 总结: MySQL explain用法 一.explain命令应用 查询数据的方 ...
- JAVA- 内部类及匿名内部类
普通类,我们平时见到的那种类,就是一个后缀为.java的文件中,直接定义的类,比如 public Cat{ private String name; private int age; } 内部类, 内 ...