基于加密的TCPIP网络聊天软件的设计与实现Word下载.docx

上传人:b****6 文档编号:20644035 上传时间:2023-01-24 格式:DOCX 页数:15 大小:51.33KB
下载 相关 举报
基于加密的TCPIP网络聊天软件的设计与实现Word下载.docx_第1页
第1页 / 共15页
基于加密的TCPIP网络聊天软件的设计与实现Word下载.docx_第2页
第2页 / 共15页
基于加密的TCPIP网络聊天软件的设计与实现Word下载.docx_第3页
第3页 / 共15页
基于加密的TCPIP网络聊天软件的设计与实现Word下载.docx_第4页
第4页 / 共15页
基于加密的TCPIP网络聊天软件的设计与实现Word下载.docx_第5页
第5页 / 共15页
点击查看更多>>
下载资源
资源描述

基于加密的TCPIP网络聊天软件的设计与实现Word下载.docx

《基于加密的TCPIP网络聊天软件的设计与实现Word下载.docx》由会员分享,可在线阅读,更多相关《基于加密的TCPIP网络聊天软件的设计与实现Word下载.docx(15页珍藏版)》请在冰豆网上搜索。

基于加密的TCPIP网络聊天软件的设计与实现Word下载.docx

对于实例服务端用TcpListener监听,然后把连接的对象实例化为一个TcpClient,调用TcpClient.GetStream()方法,返回网络流实例化为一个NetworlStream流,然后进行Send,Receive。

2、使用对称加密传输流程分析

本程序使用DESCryptoServiceProvider类实现DES对称加密运算。

服务器端:

首先从客户端接收共密钥,然后使用公共密钥加密未来使用的对称密钥,再将加密了的对称密钥发给客户端,最后才给客户端发送加密了的信息!

客户端:

首先建立和发送公共密钥给服务器,然后从服务器接受加密的对称密钥,再解密该对称密钥将它作为自己私有的不对称密钥,最后才接收信息!

3详细代码设计

服务器端开发的详细代码:

//添加的命名空间引用(原始生成的略)

usingSystem.Net;

usingSystem.Net.Sockets;

usingSystem.Threading;

usingSystem.IO;

usingSystem.Security.Cryptography;

namespaceEncryptedTcpServer

{

publicpartialclassFormServer:

Form

{

//连接的用户

System.Collections.Generic.List<

User>

userList=newList<

();

privatedelegatevoidSetListBoxCallback(stringstr);

privateSetListBoxCallbacksetListBoxCallback;

privatedelegatevoidSetComboBoxCallback(Useruser);

privateSetComboBoxCallbacksetComboBoxCallback;

//使用的本机IP地址

IPAddresslocalAddress;

//监听端口

privateintport=6788;

//和书上一样

privateTcpListenermyListener;

publicFormServer()

InitializeComponent();

listBoxStatus.HorizontalScrollbar=true;

setListBoxCallback=newSetListBoxCallback(SetListBox);

setComboBoxCallback=newSetComboBoxCallback(AddComboBoxitem);

IPAddress[]addrIP=Dns.GetHostAddresses(Dns.GetHostName());

localAddress=addrIP[0];

buttonStop.Enabled=false;

}

//开始监听

privatevoidbuttonStart_Click(objectsender,EventArgse)

myListener=newTcpListener(localAddress,port);

myListener.Start();

SetListBox(string.Format("

开始在{0}:

{1}监听客户连接"

localAddress,port));

//创建一个线程监听客户端连接请求

ThreadStartts=newThreadStart(ListenClientConnect);

ThreadmyThread=newThread(ts);

myThread.Start();

buttonStart.Enabled=false;

buttonStop.Enabled=true;

//接收客户端连接的线程

privatevoidListenClientConnect()

while(true)

TcpClientnewClient=null;

try

//等待用户进入

newClient=myListener.AcceptTcpClient();

catch

//当单击“停止监听”或者退出此窗体时AcceptTcpClient()会产生异常,因此可以利用此异常退出循环

break;

//每接受一个客户端连接,就创建一个对应的线程循环接收该客户端发来的信息

ParameterizedThreadStartpts=newParameterizedThreadStart(ReceiveData);

ThreadthreadReceive=newThread(pts);

Useruser=newUser(newClient);

threadReceive.Start(user);

userList.Add(user);

AddComboBoxitem(user);

[{0}]进入"

newClient.Client.RemoteEndPoint));

当前连接用户数:

{0}"

userList.Count));

//接收、处理客户端信息的线程,每客户1个线程,参数用于区分是哪个客户

privatevoidReceiveData(objectobj)

Useruser=(User)obj;

TcpClientclient=user.client;

//是否正常退出接收线程

boolnormalExit=false;

//用于控制是否退出循环

boolexitWhile=false;

while(exitWhile==false)

//保存接收的命令字符串

stringreceiveString=null;

//每条命令均带有一个参数,值为true或者false,表示是否有紧跟的字节数组

string[]splitString=null;

byte[]receiveBytes=null;

//从网络流中读出命令字符串

//此方法会自动判断字符串长度前缀,并根据长度前缀读出字符串

receiveString=user.br.ReadString();

splitString=receiveString.Split('

'

);

if(splitString[1]=="

true"

//先从网络流中读出32位的长度前缀

intbytesLength=user.br.ReadInt32();

//然后读出指定长度的内容保存到字节数组中

receiveBytes=user.br.ReadBytes(bytesLength);

//底层套接字不存在时会出现异常

SetListBox("

接收数据失败"

if(receiveString==null)

if(normalExit==false)

//如果停止了监听,Connected为false

if(client.Connected==true)

SetListBox(string.Format(

"

与[{0}]失去联系,已终止接收该用户信息"

client.Client.RemoteEndPoint));

来自[{0}]:

{1}"

user.client.Client.RemoteEndPoint,receiveString));

if(receiveBytes!

=null)

user.client.Client.RemoteEndPoint,Encoding.Default.GetString(receiveBytes)));

switch(splitString[0])//公钥和私钥的加密解密实现

{

case"

rsaPublicKey"

:

user.rsa.FromXmlString(Encoding.Default.GetString(receiveBytes));

//加密对称加密的私钥

byte[]encryptedKey=user.rsa.Encrypt(user.tdes.Key,false);

SendToClient(user,"

tdesKey,true"

encryptedKey);

//加密IV

byte[]encryptedIV=user.rsa.Encrypt(user.tdes.IV,false);

tdesIV,true"

encryptedIV);

catch(Exceptionerr)

MessageBox.Show(err.Message);

Logout"

//格式:

Logout

[{0}]退出"

user.client.Client.RemoteEndPoint));

normalExit=true;

exitWhile=true;

Talk"

//解密

stringtalkString=DecryptText(receiveBytes,user.tdes.Key,user.tdes.IV);

if(talkString!

[{0}]说:

client.Client.RemoteEndPoint,talkString));

default:

什么意思啊:

"

+receiveString);

userList.Remove(user);

client.Close();

//对称加密算法加密数据的具体实现

privatebyte[]EncryptText(stringstr,byte[]Key,byte[]IV)

//创建一个内存流

MemoryStreammemoryStream=newMemoryStream();

//使用传递的私钥和IV创建加密流

CryptoStreamcryptoStream=newCryptoStream(memoryStream,

newTripleDESCryptoServiceProvider().CreateEncryptor(Key,IV),

CryptoStreamMode.Write);

//将传递的字符串转换为字节数组

byte[]toEncrypt=Encoding.UTF8.GetBytes(str);

//将字节数组写入加密流,并清除缓冲区

cryptoStream.Write(toEncrypt,0,toEncrypt.Length);

cryptoStream.FlushFinalBlock();

//得到加密后的字节数组

byte[]encryptedBytes=memoryStream.ToArray();

returnencryptedBytes;

加密出错:

+err.Message);

returnnull;

finally

cryptoStream.Close();

memoryStream.Close();

//使用对称加密算法解密接收的数据

privatestringDecryptText(byte[]dataBytes,byte[]Key,byte[]IV)

//根据加密后的字节数组创建一个内存流

MemoryStreammemoryStream=newMemoryStream(dataBytes);

//使用传递的私钥、IV和内存流创建解密流

newTripleDESCryptoServiceProvider().CreateDecryptor(Key,IV),

CryptoStreamMode.Read);

//创建一个字节数组保存解密后的数据

byte[]decryptBytes=newbyte[dataBytes.Length];

//从解密流中将解密后的数据读到字节数组中

cryptoStream.Read(decryptBytes,0,decryptBytes.Length);

//得到解密后的字符串

stringdecryptedString=Encoding.UTF8.GetString(decryptBytes);

returndecryptedString;

解密出错:

//发送信息到客户端

privatevoidSendToClient(Useruser,stringcommand,byte[]bytes)

string[]splitCommand=command.Split('

//先将命令字符串写入网络流,此方法会自动附加字符串长度前缀

user.bw.Write(command);

向[{0}]发送:

user.client.Client.RemoteEndPoint,command));

if(splitCommand[1]=="

//先将字节数组的长度(32位整数)写入网络流

user.bw.Write(bytes.Length);

//然后将字节数组写入网络流

user.bw.Write(bytes);

user.bw.Flush();

user.client.Client.RemoteEndPoint,Encoding.UTF8.GetString(bytes)));

if(splitCommand[0]=="

加密前内容:

+textBoxSend.Text);

向[{0}]发送信息失败"

privatevoidAddComboBoxitem(Useruser)

if(comboBoxReceiver.InvokeRequired==true)

this.Invoke(setComboBoxCallback,user);

else

comboBoxReceiver.Items.Add(user.client.Client.RemoteEndPoint);

privatevoidSetListBox(stringstr)

if(listBoxStatus.InvokeRequired==true)

this.Invoke(setListBoxCallback,str);

listBoxStatus.Items.Add(str);

listBoxStatus.SelectedIndex=listBoxStatus.Items.Count-1;

listBoxStatus.ClearSelected();

//单击停止监听按钮触发的事件

privatevoidbuttonStop_Click(objectsender,EventArgse)

目前连接用户数:

开始停止服务,并依次使用户退出!

for(inti=0;

i<

userList.Count;

i++)

comboBoxReceiver.Items.Remove(userList[i].client.Client.RemoteEndPoint);

userList[i].bw.Close();

userList[i].br.Close();

userList[i].client.Close();

//通过停止监听让myListener.AcceptTcpClient()产生异常退出监听线程

myListener.Stop();

buttonStart.Enabled=true;

//单击发送按钮的Click事件

privatevoidbuttonSend_Click(objectsender,EventArgse)

intindex=comboBoxReceiver.SelectedIndex;

if(index==-1)

MessageBox.Show("

请先选择接收方,然后再单击[发送]"

Useruser=(User)userList[index];

//加密textBoxSend.Text的内容

byte[]encryptedBytes=EncryptText(textBoxSend.Text,user.tdes.Key,user.tdes.IV);

if(encryptedBytes!

Talk,true"

encryptedBytes);

textBoxSend.Clear();

privatevoidFormServer_FormClosing(objectsender,FormClosingEventArgse)

//未单击开始监听就直接退出时,myListener为null

if(myListener!

buttonStop_Click(null,null);

//textBoxSend获得焦点并释放按键后触发的事件

privatevoidtextBoxSend_KeyPres

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 成人教育 > 自考

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1