📄 sockets.cs
字号:
// Client-server helpers for TCP/IP
// ClientInfo: wrapper for a socket which throws
// Receive events, and allows for messaged communication (using
// a specified character as end-of-message)
// Server: simple TCP server that throws Connect events
// ByteBuilder: utility class to manage byte arrays built up
// in multiple transactions
// (C) Richard Smith 2005-7
// bobjanova@gmail.com
// You can use this for free and give it to people as much as you like
// as long as you leave a credit to me :).
// Code to connect to a SOCKS proxy modified from
// http://www.thecodeproject.com/csharp/ZaSocks5Proxy.asp
using System;
using System.IO;
using System.Net;
using System.Text;
using System.Threading;
using System.Collections;
using System.Net.Sockets;
namespace RedCorona.Net {
public delegate void ConnectionRead(ClientInfo ci, String text);
public delegate void ConnectionClosed(ClientInfo ci);
public delegate void ConnectionReadBytes(ClientInfo ci, byte[] bytes, int len);
public delegate void ConnectionReadMessage(ClientInfo ci, uint code, byte[] bytes, int len);
public enum ClientDirection {In, Out, Left, Right, Both};
public enum MessageType {Unmessaged, EndMarker, Length, CodeAndLength};
// OnReadBytes: catch the raw bytes as they arrive
// OnRead: for text ended with a marker character
// OnReadMessage: for binary info on a messaged client
public class ClientInfo {
internal Server server = null;
private Socket sock;
private String buffer;
public ConnectionRead OnRead;
public ConnectionClosed OnClose;
public ConnectionReadBytes OnReadBytes;
public ConnectionReadMessage OnReadMessage;
public MessageType MessageType;
private ClientDirection dir;
int id;
bool alreadyclosed = false;
public static int NextID = 100;
//private ClientThread t;
public object Data = null;
private char delim;
public const int BUFSIZE = 1024;
byte[] buf = new byte[BUFSIZE];
ByteBuilder bytes = new ByteBuilder(10);
byte[] msgheader = new byte[8];
byte headerread = 0;
public char Delimiter {
get { return delim; }
set { delim = value; }
}
public ClientDirection Direction { get { return dir; } }
public Socket Socket { get { return sock; } }
public Server Server { get { return server; } }
public int ID { get { return id; } }
public bool Closed {
get { return !sock.Connected; }
}
public ClientInfo(Socket cl, bool StartNow) : this(cl, null, null, ClientDirection.Both, StartNow) {}
public ClientInfo(Socket cl, ConnectionRead read, ConnectionReadBytes readevt, ClientDirection d) : this(cl, read, readevt, d, true) {}
public ClientInfo(Socket cl, ConnectionRead read, ConnectionReadBytes readevt, ClientDirection d, bool StartNow){
sock = cl; buffer = ""; OnReadBytes = readevt;
OnRead = read;
MessageType = MessageType.EndMarker;
dir = d; delim = '\n';
id = NextID; // Assign each client an application-unique ID
unchecked{NextID++;}
//t = new ClientThread(this);
if(StartNow) BeginReceive();
}
public void BeginReceive(){
// t.t.Start();
sock.BeginReceive(buf, 0, BUFSIZE, 0, new AsyncCallback(ReadCallback), this);
}
public String Send(String text){
byte[] ba = Encoding.UTF8.GetBytes(text);
String s = "";
for(int i = 0; i < ba.Length; i++) s += ba[i] + " ";
sock.Send(ba);
return s;
}
public void SendMessage(uint code, byte[] bytes){ SendMessage(code, bytes, 0, bytes.Length); }
public void SendMessage(uint code, byte[] bytes, byte paramType){ SendMessage(code, bytes, paramType, bytes.Length); }
public void SendMessage(uint code, byte[] bytes, byte paramType, int len){
if(paramType > 0){
ByteBuilder b = new ByteBuilder(3);
b.AddParameter(bytes, paramType);
bytes = b.Read(0, b.Length);
len = bytes.Length;
}
lock(sock){
switch(MessageType){
case MessageType.CodeAndLength:
sock.Send(UintToBytes(code));
sock.Send(IntToBytes(len));
break;
case MessageType.Length:
sock.Send(IntToBytes(len));
break;
}
sock.Send(bytes, len, SocketFlags.None);
}
}
public bool MessageWaiting(){
FillBuffer(sock);
return buffer.IndexOf(delim) >= 0;
}
public String Read(){
//FillBuffer(sock);
int p = buffer.IndexOf(delim);
if(p >= 0){
String res = buffer.Substring(0, p);
buffer = buffer.Substring(p + 1);
return res;
} else return "";
}
private void FillBuffer(Socket sock){
byte[] buf = new byte[256];
int read;
while(sock.Available != 0){
read = sock.Receive(buf);
if(OnReadBytes != null) OnReadBytes(this, buf, read);
buffer += Encoding.UTF8.GetString(buf, 0, read);
}
}
void ReadCallback(IAsyncResult ar){
try {
int read = sock.EndReceive(ar);
//Console.WriteLine("Socket "+ID+" read "+read+" bytes");
if(read > 0){
DoRead(buf, read);
BeginReceive();
} else {
Close();
}
} catch(SocketException){ Close(); } catch(ObjectDisposedException){ Close(); }
}
internal void DoRead(byte[] buf, int read){
if(read > 0){
if(OnReadBytes != null) OnReadBytes(this, buf, read);
if(OnRead != null){ // Simple text mode
buffer += Encoding.UTF8.GetString(buf, 0, read);
while(buffer.IndexOf(delim) >= 0) OnRead(this, Read());
}
}
ReadInternal(buf, read);
}
void ReadInternal(byte[] buf, int read){
if((OnReadMessage != null) && (MessageType != MessageType.Unmessaged)){
// Messaged mode
int copied;
uint code = 0;
switch(MessageType){
case MessageType.CodeAndLength:
case MessageType.Length:
int length;
if(MessageType == MessageType.Length){
copied = FillHeader(ref buf, 4, read);
if(headerread < 4) break;
length = GetInt(msgheader, 0, 4);
} else{
copied = FillHeader(ref buf, 8, read);
if(headerread < 8) break;
code = (uint)GetInt(msgheader, 0, 4);
length = GetInt(msgheader, 4, 4);
}
bytes.Add(buf, 0, read - copied);
if(bytes.Length >= length){
// A message was received!
headerread = 0;
byte[] msg = bytes.Read(0, length);
OnReadMessage(this, code, msg, length);
// Don't forget to put the rest through the mill
byte[] whatsleft = bytes.Read(length, bytes.Length - length);
bytes.Clear();
if(whatsleft.Length > 0) ReadInternal(whatsleft, whatsleft.Length);
}
//if(OnStatus != null) OnStatus(this, bytes.Length, length);
break;
}
}
}
int FillHeader(ref byte[] buf, int to, int read) {
int copied = 0;
if(headerread < to){
// First copy the header into the header variable.
for(int i = 0; (i < read) && (headerread < to); i++, headerread++, copied++){
msgheader[headerread] = buf[i];
}
}
if(copied > 0){
// Take the header bytes off the 'message' section
byte[] newbuf = new byte[read - copied];
for(int i = 0; i < newbuf.Length; i++) newbuf[i] = buf[i + copied];
buf = newbuf;
}
return copied;
}
public static int GetInt(byte[] ba, int from, int len){
int r = 0;
for(int i = 0; i < len; i++)
r += ba[from + i] << ((len - i - 1) * 8);
return r;
}
public static int[] GetIntArray(byte[] ba){
int[] res = new int[ba.Length / 4];
for(int i = 0; i < res.Length; i++){
res[i] = GetInt(ba, i * 4, 4);
}
return res;
}
public static uint[] GetUintArray(byte[] ba){
uint[] res = new uint[ba.Length / 4];
for(int i = 0; i < res.Length; i++){
res[i] = (uint)GetInt(ba, i * 4, 4);
}
return res;
}
public static byte[] IntToBytes(int val){ return UintToBytes((uint)val); }
public static byte[] UintToBytes(uint val){
byte[] res = new byte[4];
for(int i = 3; i >= 0; i--){
res[i] = (byte)val; val >>= 8;
}
return res;
}
public static byte[] IntArrayToBytes(int[] val){
byte[] res = new byte[val.Length * 4];
for(int i = 0; i < val.Length; i++){
byte[] vb = IntToBytes(val[i]);
res[(i * 4)] = vb[0];
res[(i * 4) + 1] = vb[1];
res[(i * 4) + 2] = vb[2];
res[(i * 4) + 3] = vb[3];
}
return res;
}
public static byte[] UintArrayToBytes(uint[] val){
byte[] res = new byte[val.Length * 4];
for(uint i = 0; i < val.Length; i++){
byte[] vb = IntToBytes((int)val[i]);
res[(i * 4)] = vb[0];
res[(i * 4) + 1] = vb[1];
res[(i * 4) + 2] = vb[2];
res[(i * 4) + 3] = vb[3];
}
return res;
}
public void Close(){
if(!alreadyclosed){
if(server != null) server.ClientClosed(this);
if(OnClose != null) OnClose(this);
alreadyclosed = true;
}
sock.Close();
}
}
public class Sockets {
// Socks proxy inspired by http://www.thecodeproject.com/csharp/ZaSocks5Proxy.asp
public static SocksProxy SocksProxy;
public static bool UseSocks = false;
public static Socket CreateTCPSocket(String address, int port){return CreateTCPSocket(address, port, UseSocks, SocksProxy);}
public static Socket CreateTCPSocket(String address, int port, bool useSocks, SocksProxy proxy){
Socket sock;
if(useSocks) sock = ConnectToSocksProxy(proxy.host, proxy.port, address, port, proxy.username, proxy.password);
else {
IPAddress host = Dns.GetHostByName(address).AddressList[0];
sock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
sock.Connect(new IPEndPoint(host, port));
}
return sock;
}
private static string[] errorMsgs= {
"Operation completed successfully.",
"General SOCKS server failure.",
"Connection not allowed by ruleset.",
"Network unreachable.",
"Host unreachable.",
"Connection refused.",
"TTL expired.",
"Command not supported.",
"Address type not supported.",
"Unknown error."
};
public static Socket ConnectToSocksProxy(IPAddress proxyIP, int proxyPort, String destAddress, int destPort, string userName, string password){
byte[] request = new byte[257];
byte[] response = new byte[257];
ushort nIndex;
IPAddress destIP = null;
try{ destIP = IPAddress.Parse(destAddress); }
catch { }
IPEndPoint proxyEndPoint = new IPEndPoint(proxyIP, proxyPort);
// open a TCP connection to SOCKS server...
Socket s;
s = new Socket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp);
s.Connect(proxyEndPoint);
/* } catch(SocketException){
throw new SocketException(0, "Could not connect to proxy server.");
}*/
nIndex = 0;
request[nIndex++]=0x05; // Version 5.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -