生活随笔
收集整理的這篇文章主要介紹了
C# Socket编程实现简单的局域网聊天器
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
前言
最近在學習C# Socket相關的知識,學習之余,動手做了一個簡單的局域網聊天器。有萌生做這個的想法,主要是由于之前家里兩臺電腦之間想要傳輸文件十分麻煩,需要借助QQ,微信或者其他第三方應用,基本都要登錄,而且可能傳輸的文件還有大小限制,壓縮問題。所以本聊天器的首要目標就是解決這兩個問題,做到使用方便(雙擊啟動即用),傳文件無限制。
廢話不多說,先上圖。S-Chat是服務端,C-Chat是客戶端,兩者除了客戶端首次啟動后需要設置一下連接的IP地址外,無其他區別。操作與界面都完全相同,對于用戶來說,基本不用在意誰是服務端誰是客戶端。
編碼
服務端監聽接口
服務端主要負責開啟監聽線程,等待客戶端接入
public void StartListen()
{Socket socket
= GetSocket();socket
.Bind(this.GetIPEndPoint());socket
.Listen(1);Thread acceptThread
= new Thread(new ThreadStart(TryAccept
));acceptThread
.IsBackground
= true;acceptThread
.Start();
}public void TryAccept()
{Socket socket
= GetSocket();while (true){try{Socket connectedSocket
= socket
.Accept()this.ConnectedSocket
= connectedSocket
;OnConnect(); this.StartReceive(); break;}catch (Exception e
){}}
}
客戶端連接接口
客戶端主要負責開啟連接線程,每隔2秒,自動嘗試連接服務端
public void StartConnect()
{Thread connectThread
= new Thread(new ThreadStart(TryConnect
));connectThread
.IsBackground
= true;connectThread
.Start();
}public void TryConnect()
{Socket socket
= GetSocket();while (true){try{socket
.Connect(this.GetIPEndPoint());this.ConnectedSocket
= socket
;OnConnect(); this.StartReceive();break;}catch (Exception e
){Thread
.Sleep(TryConnectInterval
); }}
}
文字發送,文件發送,接收文字,接收文件等通用接口主要實現在ChatBase類中,是服務端與客戶端的共同父類。
文字發送接口
發送數據的第一位表示發送信息的類型,0表示字符串文字,1表示文件
然后獲取待發送字符串的長度,使用long類型表示,占用8個字節
共發送的字節數據可以表示為頭部(類型 + 字符串字節長度,共9個字節)+ 實際字符串字節數據
public bool Send(string msg
)
{if (ConnectedSocket
!= null && ConnectedSocket
.Connected
){byte[] buffer
= UTF8
.GetBytes(msg
); byte[] len
= BitConverter
.GetBytes((long)buffer
.Length
); byte[] content
= new byte[1 + len
.Length
+ buffer
.Length
]; content
[0] = (byte)ChatType
.Str
; Array
.Copy(len
, 0, content
, 1, len
.Length
); Array
.Copy(buffer
, 0, content
, 1 + len
.Length
, buffer
.Length
); try{ConnectedSocket
.Send(content
);return true;}catch (Exception e
){}}return false;
}
文件發送接口
與字符串發送相同的頭部可以表示為(類型 + 文件長度,共9個字節)
還需要再加上待發送的文件名的長度,與文件名字節數據
共發送的字節數據可以表示為頭部(類型 + 文件長度,共9個字節)+ 文件名頭部(文件名長度 + 文件名字節數據)+ 實際文件數據
public bool SendFile(string path
)
{if (ConnectedSocket
!= null && ConnectedSocket
.Connected
){try{FileInfo fi
= new FileInfo(path
);byte[] len
= BitConverter
.GetBytes(fi
.Length
); byte[] name
= UTF8
.GetBytes(fi
.Name
); byte[] nameLen
= BitConverter
.GetBytes(name
.Length
); byte[] head
= new byte[1 + len
.Length
+ nameLen
.Length
+ name
.Length
];head
[0] = (byte)ChatType
.File
; Array
.Copy(len
, 0, head
, 1, len
.Length
); Array
.Copy(nameLen
, 0, head
, 1 + len
.Length
, nameLen
.Length
); Array
.Copy(name
, 0, head
, 1 + len
.Length
+ nameLen
.Length
, name
.Length
); ConnectedSocket
.SendFile(path
,head
,null,TransmitFileOptions
.UseDefaultWorkerThread
);return true;}catch(Exception e
){}}return false;
}
信息接收接口(文字與文件)
主要是解析接收到的字節數據,根據字符串或文件的類型進行處理
public void Receive()
{if (ConnectedSocket
!= null){while (true){try{byte[] head
= new byte[9];ConnectedSocket
.Receive(head
, head
.Length
, SocketFlags
.None
);int len
= BitConverter
.ToInt32(head
, 1);if (head
[0] == (byte) ChatType
.Str
){byte[] buffer
= new byte[len
];ConnectedSocket
.Receive(buffer
, len
, SocketFlags
.None
);OnReceive(ChatType
.Str
, UTF8
.GetString(buffer
));}else if(head
[0] == (byte)ChatType
.File
){if (!Directory
.Exists(dirName
)){Directory
.CreateDirectory(dirName
);}byte[] nameLen
= new byte[4];ConnectedSocket
.Receive(nameLen
, nameLen
.Length
, SocketFlags
.None
);byte[] name
= new byte[BitConverter.ToInt32(nameLen
, 0)];ConnectedSocket
.Receive(name
, name
.Length
, SocketFlags
.None
);string fileName
= UTF8
.GetString(name
);int readByte
= 0;int count
= 0;byte[] buffer
= new byte[1024 * 8];string filePath
= Path
.Combine(dirName
, fileName
);if (File
.Exists(filePath
)){File
.Delete(filePath
);}using (FileStream fs
= new FileStream(filePath
, FileMode
.Append
, FileAccess
.Write
)){while (count
!= len
){int readLength
= buffer
.Length
;if(len
- count
< readLength
){readLength
= len
- count
;}readByte
= ConnectedSocket
.Receive(buffer
, readLength
, SocketFlags
.None
);fs
.Write(buffer
, 0, readByte
);count
+= readByte
;}}OnReceive(ChatType
.File
, fileName
); }else{}}catch (Exception e
){}}}
}
使用
第一次vb.net教程使用,客戶java基礎端需要python基礎教程設置待連接的IP地址。之后再啟動會自動連接
雙擊服務端exe啟動,點擊設置,查看IP地址項
雙擊客戶端exe啟動,點擊設置,在IP地址項,輸入服務端查看到的IP地址
設置成功后,等待大約一兩秒,應用c#教程cion變成綠色,即表示連接成功,可以正常發送sql語句文字和文件了
可以點擊選擇文件(支持選擇多個文件),發送文件
支持直接拖拽文件到輸入框,發送文件
支持Ctrl+Enter快捷鍵發送
接收到的文件自動存放在exe所在目錄的ChatFiles文件夾下
注意事項
客戶端服務端需要在同一個局域網下才能實現連接
服務端IP地址是不支持修改的,自動讀取本機的IP地址
源碼
完整代碼放在GitHub上,點擊查看
預編譯好的可運行exe程序,在倉庫的Release目錄,也可以直接通過百度云下載,提取碼v4pe
作者:iwiniwin
出處:http://www.cnblogs.com/iwiniwin/
總結
以上是生活随笔為你收集整理的C# Socket编程实现简单的局域网聊天器的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。