📄 wintalk.cs
字号:
// Finalize a talker
~Talker(){
Dispose();
}
// Dispose of resources and surpress finalization
public void Dispose(){
GC.SuppressFinalize(this);
if(reader != null){
reader.Close();
reader = null;
}
if(writer != null){
writer.Close();
writer = null;
}
if(socket != null){
socket.Close();
socket = null;
}
}
// Nested delegat class and matchine event
public delegate
void NotificationCallback(Notification notify, Object data);
public event NotificationCallback Notifications;
// Nested enum for notifications
public enum Notification{
Initialized = 1,
StatusChange,
ReceivedRefresh,
ReceivedAppend,
End,
Error
}
// Nested enum for supported states
public enum Status{
Listening,
Connected
}
// Start up the talker's functionality
public void Start(){
ThreadPool.QueueUserWorkItem(new WaitCallback(EstablishSocket));
}
// Send text to remote connection
public void SendTalk(String newText){
String send;
// NetworkStream stream = null;
// Is this an append
if((prevSendText.Length <= newText.Length) && String.CompareOrdinal(
newText, 0, prevSendText, 0, prevSendText.Length)==0){
String append = newText.Substring(prevSendText.Length);
send = String.Format("A{0}:{1}", append.Length, append);
// or a complete replacement
}else{
send = String.Format("R{0}:{1}", newText.Length, newText);
}
// Send the data and flush it out
// socket = new Socket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp);
// socket.Blocking = true;
// socket.Connect(endPoint);
// stream = new NetworkStream(socket);
// reader = new StreamReader(stream);
// writer = new StreamWriter(stream);
writer.Write(send);
writer.Flush();
// Save the text for future comparison
prevSendText = newText;
}
// Send a status notification
private void SetStatus(Status status){
this.status = status;
Notifications(Notification.StatusChange, status);
}
// Establish a socket connection and start receiving
private void EstablishSocket(Object state){
NetworkStream stream = null;
try{
// If not client, setup listner
if(!client){
Socket listener;
try{
listener = new Socket(AddressFamily.InterNetwork,
SocketType.Stream, ProtocolType.Tcp);
listener.Blocking = true;
listener.Bind(endPoint);
SetStatus(Status.Listening);
listener.Listen(0);
socket = listener.Accept();
listener.Close();
stream = new NetworkStream(socket);
reader = new StreamReader(stream);
writer = new StreamWriter(stream);
writer.Write("WINTALK .NET");
writer.Flush();
}catch(SocketException e){
// If there is already a listener on this port try client
if(e.ErrorCode == 10048){
client = true;
endPoint = new IPEndPoint(
Dns.Resolve("127.0.0.1").AddressList[0], endPoint.Port);
}else{
Notifications(
Notification.Error,
"Error Initializing Socket:\n"+e.ToString());
}
}
}
// Try a client connection
if(client){
Socket temp = new
Socket(AddressFamily.InterNetwork,
SocketType.Stream,ProtocolType.Tcp);
temp.Blocking = true;
temp.Connect(endPoint);
socket = temp;
socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReceiveTimeout, 5000);
socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.SendTimeout, 5000);
stream = new NetworkStream(socket);
reader = new StreamReader(stream);
writer = new StreamWriter(stream);
char[] handshake = new char[12];
try
{
if (!(reader.Read(handshake,0,12)>0 && new string(handshake)=="WINTALK .NET"))
{
socket.Close();
socket = null;
}
else
{
socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReceiveTimeout , 0);
socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.SendTimeout, 0);
}
}
catch
{
socket.Close();
socket = null;
}
}
// If it all worked out, create stream objects
if(socket != null){
SetStatus(Status.Connected);
Notifications(Notification.Initialized, this);
// Start receiving talk
// Note: on w2k and later platforms, the NetworkStream.Read()
// method called in ReceiveTalk will generate an exception when
// the remote connection closes. We handle this case in our
// catch block below.
ReceiveTalk();
// On Win9x platforms, NetworkStream.Read() returns 0 when
// the remote connection closes, prompting a graceful return
// from ReceiveTalk() above. We will generate a Notification.End
// message here to handle the case and shut down the remaining
// WinTalk instance.
Notifications(Notification.End, "Remote connection has closed.");
}
else
{
Notifications(Notification.Error,
"Failed to Establish Socket, did you specify the correct port?");
}
}catch(IOException e){
SocketException sockExcept = e.InnerException as SocketException;
if(sockExcept != null && 10054 == sockExcept.ErrorCode){
Notifications(Notification.End, "Remote connection has closed.");
}else{
if (Notifications != null)
Notifications(Notification.Error, "Socket Error:\n"+e.Message);
}
}catch(Exception e){
Notifications(Notification.Error, "Socket Error:\n"+e.Message);
}
}
// Receive chat from remote client
private void ReceiveTalk(){
char[] commandBuffer = new char[20];
char[] oneBuffer = new char[1];
int readMode = 1;
int counter = 0;
StringBuilder text = new StringBuilder();
while(readMode != 0){
if(reader.Read(oneBuffer, 0, 1)==0){
readMode = 0;
continue;
}
switch(readMode){
case 1:
if(counter == commandBuffer.Length){
readMode = 0;
continue;
}
if(oneBuffer[0] != ':'){
commandBuffer[counter++] = oneBuffer[0];
}else{
counter = Convert.ToInt32(
new String(commandBuffer, 1, counter-1));
if(counter>0){
readMode = 2;
text.Length = 0;
}else if(commandBuffer[0] == 'R'){
counter = 0;
prevReceiveText = String.Empty;
Notifications(Notification.ReceivedRefresh, prevReceiveText);
}
}
break;
case 2:
text.Append(oneBuffer[0]);
if(--counter == 0){
switch(commandBuffer[0]){
case 'R':
prevReceiveText = text.ToString();
Notifications(Notification.ReceivedRefresh, prevReceiveText);
break;
default:
string newText = text.ToString();
prevReceiveText += newText;
Notifications(Notification.ReceivedAppend, newText);
break;
}
readMode = 1;
}
break;
default:
readMode = 0;
continue;
}
}
}
private Socket socket;
private TextReader reader;
private TextWriter writer;
bool client;
IPEndPoint endPoint;
private String prevSendText;
private String prevReceiveText;
private String statusText;
private Status status;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -