这两天在网上看了些视频,写了一个简单的聊天室的功能:想把它分享出来!以至于忘记!希望大家看过以后 提哈意见!
窗口设计样式如图:
服务端:
就是说哈如何获得IP地址了,我用的方法就是在运行里---cmd--ipconfig来获得ip地址,我当时乱写的IP地址根本不行:所以写这种方法,希望这个方法能帮助在这里遇到同样的问题的朋友们!虽然我是一个菜鸟!但是我想程序写的明了!
下面就是关于引用:这里因为要用到多线程、用到套节字、操作文件所以引用相应的类!
下面为客户端的代码:
using System.Net;
using System.Net.Sockets;
using System.Threading;
using System.IO;
namespace QQ1
{
public partial class Clinet : Form
{
public Clinet()
{
InitializeComponent();
TextBox.CheckForIllegalCrossThreadCalls = false;
}
Socket requestCon = null;
#region 建立连接
private void btnSendCon_Click(object sender, EventArgs e)
{
IPAddress IP = IPAddress.Parse(txtIP.Text.ToString().Trim());
IPEndPoint endPoint = new IPEndPoint(IP, int.Parse(txtPort.Text.ToString()));
requestCon = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
requestCon.Connect(endPoint);
Thread threadReceive = new Thread(ReceiveMsg);
threadReceive.IsBackground = true;
threadReceive.Start();
}
#endregion
#region 显示所有的消息(发送和收到的)
public void ShowAllMsg(string Msg)
{
txtShowAllMsg.AppendText(Msg + "\n");
}
#endregion
#region 发送信息
private void btnSend_Click(object sender, EventArgs e)
{
string sendMsg = txtSendMsg.Text.ToString().Trim();
byte[] arrSendMsg = Encoding.UTF8.GetBytes(sendMsg);
byte[] arrsengMsgAgain = new byte[arrSendMsg.Length + 1];
Buffer.BlockCopy(arrSendMsg, 0, arrsengMsgAgain, 1, arrSendMsg.Length);
arrsengMsgAgain[0] =0;
try
{
requestCon.Send(arrsengMsgAgain);
ShowAllMsg("你说:" + sendMsg);
}
catch (SocketException ex)
{
MessageBox.Show("接收消息发生异常" + ex.Message);//每次调用Socket对象的方法的时候 ,一定捕捉异常
}
catch(Exception ex)
{
MessageBox.Show("接收消息发生异常" + ex.Message);
}
}
#endregion
#region 收到消息
public void ReceiveMsg()
{
while (true)
{
byte[] arrRecevieMsg = new byte[1024 * 1024 * 2]
try
{
nt length = requestCon.Receive(arrRecevieMsg);//因为这里接收它一直在接收,它会阻塞线程,所以我们一定要在这里使用线程(对这个方法)!
string RecevieMsg = Encoding.UTF8.GetString(arrRecevieMsg, 0, length);//因为这里发关
ShowAllMsg("他说:" + RecevieMsg);
}
catch (SocketException ex)
{
MessageBox.Show("接收消息发生异常!" + ex.Message);
}
catch (Exception ex)
{
MessageBox.Show("接收消息发生异常!" + ex.Message);//所有与网络通信的地方都要获得异常!
}
}
}
#endregion
#region 得到路径
private void btnFindFile_Click(object sender, EventArgs e)
{
OpenFileDialog ofd = new OpenFileDialog();
if (ofd.ShowDialog() == DialogResult.OK)
{
txtFilePath.Text = ofd.FileName;
}
}
#endregion
#region 发送文件
private void btnSendFile_Click(object sender, EventArgs e)
{
using (FileStream fs = new FileStream(txtFilePath.Text, FileMode.Open))
{
byte[] arrFile = new byte[1024 * 1024 * 2];//先得到一个你想要的空间,我们这里定义的2M
int length = fs.Read(arrFile, 0, arrFile.Length);//然后调用文件文件的Read方法,把它读到这里文件里面去,从0开始,到我们定义的文件长度arrFile.Length,但是这里它有一个返回值 ,这个文件真实文件长度length!
byte[] arrSendFile = new byte[length + 1];//然后我们再声明一个新的字节数组,它的长度,就是比它的真实长度加1;
arrSendFile[0] = 1;//我们给它的字节数组的开头1,说明我想传的是文件
Buffer.BlockCopy(arrFile,0,arrSendFile,1,length);//这里就用Buffer的BlockCopy方法,它的参数第一个:原来文件!,第二参数:从什么位置开始,第三个参数:复制那个新字节数组中,第四个参数:旧文件在新文件那个位置开始复制,因为我们前面已经定义新字节数组第一个参数为0,所以我们这里要从1开始:第五参数: 这个个复制的数据有多长!
requestCon.Send(arrSendFile);//开始发送文件!
}
}
#endregion
}
}
下面是服务器端的代码:
using System.Net;
using System.Net.Sockets;
using System.Threading;
using System.IO;
namespace QQ
{
public partial class txtState : Form
{
public txtState()
{
InitializeComponent();
TextBox.CheckForIllegalCrossThreadCalls = false;
}
Socket socketWatch = null;
Dictionary
Dictionary
private void btnConnect_Click(object sender, EventArgs e)
{
IPAddress ipAddress = IPAddress.Parse(txtIP.Text.ToString().Trim());
IPEndPoint endPoint = new IPEndPoint(ipAddress, int.Parse(txtPort.Text.Trim()));
socketWatch = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
socketWatch.Bind(endPoint);
socketWatch.Listen(10);
ShowMsg("开始连接");
//socketWatch.Accept();//因为这个方法调用要阻滞程序,所以把它写在线程里面去
Thread th = new Thread(WatchRequst);//我们对监听使用线程!
th.IsBackground = true;
th.Start();
}
public void WatchRequst()
{
while (true)
{
Socket socketStart = socketWatch.Accept();//每次监听到请求,这里会创建一个SOCKET对象!,我们拿到它的那个那个IP地址发送的数据:这里使用这用socketStart.RemoteEndPoint.ToString(),拿到远程IP和Port
Thread threadReceive = new Thread(ReceiveMsg);//这样产生每个线程的时候,绑定ReceiveMsg方法
threadReceive.IsBackground = true;
threadReceive.Start(socketStart);//这里给方法传了一个SOCKET对象!每次调用的时候都是一个新的SOCKET对象
listOnLine.Items.Add(socketStart.RemoteEndPoint.ToString());//添加到列表框中
socket.Add(socketStart.RemoteEndPoint.ToString(), socketStart);//添加到字典中的Socket对象
thread.Add(socketStart.RemoteEndPoint.ToString(), threadReceive); //把线程对象添加字典中!
ShowMsg("连接成功!");
}
}
#region 添加显示到显示状态框
public void ShowMsg(string Msg)
{
txtShowConState.AppendText(Msg+"\t");
}
#endregion
# region 循环接收消息
public void ReceiveMsg(object soc)
{
Socket socketReceive = soc as Socket;//把类型进行转化
while (true)
{
byte[] arrReceive = new byte[1024 * 1024 * 2];//只设置了它的大小 没有放身体任何的东西
int length = -1;
try//当断开连接的时候会出现异常 所以这里来异常处理!
{
length=socketReceive.Receive(arrReceive);//这里方法报出异常,这里捕获异常,这里是客户端的连接突然关闭的时候报的异常
}
catch (SocketException ex)
{
ShowReceiveMsg(ex.Message);
socket.Remove(socketReceive.RemoteEndPoint.ToString());//当服务器的删除相应的SOCKET对象,这里虽然出现异常但是这里对象还在!所以我们能到拿 到对象的socketReceive.RemoteEndPoint;,因为我的字典的集合,都是使用远程的IP和Port作Key
thread.Remove(socketReceive.RemoteEndPoint.ToString());//删除Socket对应的线程
//从列表移除远程端口
listOnLine.Items.Remove(socketReceive.RemoteEndPoint.ToString());//删除列表存在的IP和port
return;
}
catch(Exception ex)
{
ShowReceiveMsg(ex.Message);
return;
}
if (arrReceive[0]==0)
{
string Msg = Encoding.UTF8.GetString(arrReceive, 1, length-1);
ShowReceiveMsg("他说:" + Msg);
}
else if (arrReceive[0] == 1)
{
SaveFileDialog sfd = new SaveFileDialog();
if (sfd.ShowDialog() == DialogResult.OK)
{
string filePath = sfd.FileName;
using (FileStream fs = new FileStream(filePath, FileMode.Create))
{
fs.Write(arrReceive, 1, length-1);
ShowReceiveMsg("接收成功!");
}
}
}
}
}
#endregion
# region 显示消息的方法
public void ShowReceiveMsg(string msg)
{
txtShowMsg.AppendText(msg+"\n");
}
#endregion
#region 发送信息
private void btnSend_Click(object sender, EventArgs e)
{
if (string.IsNullOrEmpty(listOnLine.Text))
{
MessageBox.Show("请选择发送的客户");
}
else
{
string Msg = txtSendMsg.Text.Trim().ToString();
byte[] arrSendMsg = Encoding.UTF8.GetBytes(Msg);
try
{
socket[listOnLine.Text].Send(arrSendMsg);
ShowReceiveMsg("你说:" + Msg);
}
catch (SocketException ex)
{
MessageBox.Show("发送时出现异常!" + ex.Message);//只要是socket对象跟网络连接都要来获得异常
}
catch (Exception ex)
{
MessageBox.Show("发送时出现异常!" + ex.Message);
}
}
}
#endregion
#region 找到文件所在的路径 并把它的路径给显示到文本框(txtFilePath)
private void btnFindFile_Click(object sender, EventArgs e)
{
OpenFileDialog opd = new OpenFileDialog();
if (opd.ShowDialog()==DialogResult.OK)
{
txtFilePath.Text = opd.FileName.ToString();
}
}
#endregion
}
}