C#聊天程式 (轉)
/*=====================================================================
: Wintalk.cs
摘要: 演示如何使用建立
=====================================================================*/
using System;
using System.IO;
using System.Text;
using System.Threading;
using System.Net;
using System.Net.Sockets;
using System.Drawing;
using System..Forms;
class App{
// Entry point
public static void Main(String[] args){
// If the args parse in known way then run the app
if(ParseArgs(args)){
// Create a custom Talker
Talker talker = new Talker(endPoint, client);
// Pass the object reference to a new foobject
TalkForm form = new TalkForm(talker);
// Start the talker "talking"
talker.Start();
// Run the applications message pump
Application.Run(form);
}
}
// Parsed Argument Storage
private static IPEndPoint endPoint;
private static bool client;
// Parse command line arguments
private static bool ParseArgs(String[] args){
try{
if(args.Length == 0){
client = false;
endPoint = new IPEndPoint(IPAddress.Any,5150);
return true;
}
switch(Char.ToUpper(args[0][1])){
case 'L':
int port = 5150;
if(args.Length > 1){
port = Convert.ToInt32(args[1]);
}
endPoint = new IPEndPoint(IPAddress.Any,port);
client = false;
break;
case 'C':
port = 5150;
String address = "127.0.0.1";
client = true;
if(args.Length > 1){
address = args[1];
port = Convert.ToInt32(args[2]);
}
endPoint = new IPEndPoint(.Resolve(address).Addreist[0], port);
break;
default:
ShowUsage();
return false;
}
}catch{
ShowUsage();
return false;
}
return true;
}
// Show sample usage
private static void ShowUsage(){
MessageBox.Show("WinTalk [switch] [parameters...]nn"+
" /L [port]tt-- Listens on a port. Default: 5150n"+
" /C [address] [port]t-- Connects to an address and port.nn"+
"Example Server - n"+
"Wintalk /Lnn"+
"Example Client - n"+
"Wintalk /C ServerMachine 5150","WinTalk Usage");
}
}
// UI class for the sample
class TalkForm:Form {
public TalkForm(Talker talker) {
// Associate for method with the talker object
this.talker = talker;
talker.Notifications += new
Talker.NotificationCallback(HandleTalkerNotifications);
// Create a UI elements
Splitter talkSplitter = new Splitter();
Panel talkPanel = new Panel();
receiveText = new TextBox();
sendText = new TextBox();
// we'll support up to 64k data in our text box controls
receiveText.MaxLength = sendText.MaxLength = 65536;
statusText = new Label();
// Initialize UI elements
receiveText.Dock = DockStyle.Top;
receiveText.Multiline = true;
receiveText.ScrollBars = ScrollBars.Both;
receiveText.Size = new Size(506, 192);
receiveText.TabIndex = 1;
receiveText.Text = "";
receiveText.Wrap = false;
receiveText.ReadOnly = true;
talkPanel.Anchor = (AnchorStyles.Top|AnchorStyles.Bottom
|AnchorStyles.Left|AnchorStyles.Right);
talkPanel.Controls.AddRange(new Control[] {sendText,
talkSplitter,
receiveText});
talkPanel.Size = new Size(506, 371);
talkPanel.TabIndex = 0;
talkSplitter.Dock = DockStyle.Top;
talkSplitter.Location = new Point(0, 192);
talkSplitter.Size = new Size(506, 6);
talkSplitter.TabIndex = 2;
talkSplitter.TabStop = false;
statusText.Dock = DockStyle.Bottom;
statusText.Location = new Point(0, 377);
statusText.Size = new Size(507, 15);
statusText.TabIndex = 1;
statusText.Text = "Status:";
sendText.Dock = DockStyle.Fill;
sendText.Location = new Point(0, 198);
sendText.Multiline = true;
sendText.ScrollBars = ScrollBars.Both;
sendText.Size = new Size(506, 173);
sendText.TabIndex = 0;
sendText.Text = "";
sendText.WordWrap = false;
sendText.TextChanged += new EventHandler(HandleTextChange);
sendText.Enabled = false;
AutoScaleBaseSize = new Size(5, 13);
ClientSize = new Size(507, 392);
Controls.AddRange(new Control[] {statusText,
talkPanel});
Text = "WinTalk";
this.ActiveControl = sendText;
}
// When the app closes, dispose of the talker object
protected overr void OnClosed(EventArgs e){
if(talker!=null){
// remove our notification handler
talker.Notifications -= new
Talker.NotificationCallback(HandleTalkerNotifications);
talker.Dispose();
}
base.OnClosed(e);
}
// Handle notifications from the talker object
private void HandleTalkerNotifications(
Talker.Notification notify, Object data){
switch(notify){
case Talker.Notification.Initialized:
break;
// Respond to status changes
case Talker.Notification.StatusChange:
Talker.Status status = (Talker.Status)data;
statusText.Text = String.Format("Status: {0}", status);
if(status == Talker.Status.Connected){
sendText.Enabled = true;
}
break;
// Respond to received text
case Talker.Notification.Received:
receiveText.Text = data.ToString();
receiveText.ionStart = Int32.MaxValue;
receiveText.ScrollToCaret();
break;
// Respond to error notifications
case Talker.Notification.Error:
Close(data.ToString());
break;
// Respond to end
case Talker.Notification.End:
MessageBox.Show(data.ToString(), "Closing WinTalk");
Close();
break;
default:
Close();
break;
}
}
// Handle text change notifications and send talk
private void HandleTextChange(Object sender, EventArgs e){
if(talker != null){
talker.SendTalk((sender as TextBox).Text);
}
}
// Close with an explanation
private void Close(String message){
MessageBox.Show(message, "Error!");
Close();
}
// Private UI elements
private TextBox receiveText;
private TextBox sendText;
private Label statusText;
private Talker talker;
}
// An encapsulation of the Sockets class used for socket chatting
class Talker:IDisposable{
// Construct a talker
public Talker(IPEndPoint endPoint, bool client){
this.endPoint = endPoint;
this.client = client;
socket = null;
reader = null;
writer = null;
statusText = prevSendText = prevReceiveText = String.Empty;
}
// Finalize a talker
~Talker(){
Dispose();
}
// Dispose of res and surpress finalization
public void Dispose(){
GC.Suppresinalize(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,
Received,
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;
// 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
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){
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();
}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;
}
// If it all worked out, create stream objects
if(socket != null){
SetStatus(Status.Connected);
NetworkStream stream = new NetworkStream(socket);
reader = new StreamReader(stream);
writer = new StreamWriter(stream);
Notifications(Notification.Initialized, this);
}else{
Notifications(Notification.Error,
"Failed to Establish Socket");
}
// 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 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.");
}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[] commanuffer = 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.Received, prevReceiveText);
}
}
break;
case 2:
text.Append(oneBuffer[0]);
if(--counter == 0){
switch(commandBuffer[0]){
case 'R':
prevReceiveText = text.ToString();
break;
default:
prevReceiveText += text.ToString();
break;
}
readMode = 1;
Notifications(Notification.Received, prevReceiveText);
}
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;
}
.NET SDK帶這個例子.
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/10752043/viewspace-990752/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- VB.NET聊天程式 (轉)
- C# 實現語音聊天C#
- C# 語音聊天系統C#
- c# winform程式設計轉例C#ORM程式設計
- 初用SOCKET做聊天室程式後所想到的…… (轉)
- 【轉】C# 中 強制退出WinForm程式C#ORM
- C#入門程式碼[轉載][收藏]C#
- UDP聊天程式補充UDP
- SignalR實現web線上即時聊天(C#)SignalRWebC#
- 微信小程式中將時間戳轉換為聊天格式微信小程式時間戳
- c# long?與long的轉化程式碼C#
- VB程式設計師眼中的C# (轉)程式設計師C#
- C# 程式語言的未來功能 (轉)C#
- 用c#快速實現的智慧聊天機器人C#機器人
- 強制qq聊天程式碼
- 非同步Socket寫聊天程式非同步
- java簡單聊天程式碼Java
- c#全半形轉換示例程式碼C#
- VB程式設計師眼中的C# 2 (轉)程式設計師C#
- VB程式設計師眼中的C# 4 (轉)程式設計師C#
- 程式碼換膚術(一)——C#和VB (轉)C#
- VB程式設計師眼中的C# 6 (轉)程式設計師C#
- VB程式設計師眼中的C# 3 (轉)程式設計師C#
- VB程式設計師眼中的C# 5 (轉)程式設計師C#
- VB程式設計師眼中的C# 7 (轉)程式設計師C#
- VB程式設計師眼中的C# 8 (轉)程式設計師C#
- VB程式設計師眼中的C# 9 (轉)程式設計師C#
- VB.net 跟 C# 的程式碼轉換C#
- C#下資料庫程式設計(二) (轉)C#資料庫程式設計
- 實現埠對埠的聊天 (轉)
- 微信小程式websocket聊天室微信小程式Web
- Beginner with C# (轉)C#
- WHAT IS C# (轉)C#
- 【轉】[C#] 1行程式碼實現C#複製資料夾功能C#行程
- 工程座標轉換方法C#程式碼實現C#
- MSDN 訪談錄之C#程式設計一 (轉)C#程式設計
- VB程式設計師眼中的C# 10(end) (轉)程式設計師C#
- 玩轉 PHP 網路程式設計全套之 libevent 框架多人聊天應用PHP程式設計框架