黑马程序员-我的入学笔记9-关于socket简易聊天室
2013-09-27 22:49
337 查看
---------------------- <a href="http://edu.csdn.net"target="blank">ASP.Net+Android+IO开发S</a>、<a
href="http://edu.csdn.net"target="blank">.Net培训</a>、期待与您交流! ----------------------
关于套接字下写的简易聊天室,根据视频的内容,将代码实现,还有许多需要扩展完善的地方,只是初步的了解,下面是服务端和客户端的代码.
服务端
客户端
href="http://edu.csdn.net"target="blank">.Net培训</a>、期待与您交流! ----------------------
关于套接字下写的简易聊天室,根据视频的内容,将代码实现,还有许多需要扩展完善的地方,只是初步的了解,下面是服务端和客户端的代码.
服务端
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Net;//IPAdress,IPEndPoint(ip和端口)类的命名空间 using System.Net.Sockets;//引用套接字 using System.Threading;//引用多线程 using System.Windows.Forms;//引用关于OpenFileDialog和SaveFileDialog using System.IO;//引用IO流 namespace 聊天室 { public partial class ChatSever : Form { public ChatSever() { InitializeComponent(); TextBox.CheckForIllegalCrossThreadCalls = false;//关闭对跨文本框线程的调用错误 } Thread threadConnectWatch = null;//创建一个线程用于监听客户端连接请求 Socket socketWatch = null;//创建一个套接字,服务器端负责监听 private void btnConnect_Click(object sender, EventArgs e) { //new套接字,服务器端负责监听,参数(IP4寻址协议,流逝连接,用TCP协议接收数据) socketWatch = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); //获取文本框中的IP地址对象,Parse方法,将IPiuce字符串转换成实例 IPAddress adress = IPAddress.Parse(txtIPadress.Text.Trim());//Trim方法(去除尾部空白) //创建包含IP和Point的网络节点对象 IPEndPoint endpoint = new IPEndPoint(adress, int.Parse(txtPoint.Text.Trim())); //通过Bind方法建立连接,参数(之前建立的的网络节点对象) socketWatch.Bind(endpoint); //设置监听队列的长度 socketWatch.Listen(10); ShowMsg("服务器启动监听!~~"); //开始监听客户端连接请求,注意Accept会阻断当前线程.利用多线程解决问题 //Socket socketConnection = socketWatch.Accept(); //修改如下,new一个线程,参数(wathConnect委托) threadConnectWatch = new Thread(watchConnect); threadConnectWatch.IsBackground = true;//设置成后台方法 threadConnectWatch.Start();//开启线程 } //创建一个集合,用于存储新的连接套接字 Dictionary<string,Socket> dic=new Dictionary<string,Socket>(); Dictionary<string, Thread> dicThr = new Dictionary<string, Thread>(); /// <summary> /// 负责监听客户端请求的方法 /// </summary> void watchConnect() { while (true)//服务端不断的监听 { //一旦监听到连接请求,返回一个新的套接字 Socket sokConnection = socketWatch.Accept(); //将新的套接字添加到集合中 dic.Add(sokConnection.RemoteEndPoint.ToString(),sokConnection); //每次再为每个客户端添加一个用于接收改客户端消息的线程 Thread thrReceice = new Thread(ReceiveMsg); thrReceice.IsBackground = true; thrReceice.Start(sokConnection.RemoteEndPoint.ToString()); //将线程添加到线程集合中 dicThr.Add(sokConnection.RemoteEndPoint.ToString(), thrReceice); //添加到列表栏,用唯一的ip端口字符串 lbOnline.Items.Add(sokConnection.RemoteEndPoint.ToString()); ShowMsg("与客户端连接成功!~~"+sokConnection.RemoteEndPoint.ToString()); } } /// <summary> /// 接收客户端数据的方法 /// </summary> /// <param name="sokConnects"></param> void ReceiveMsg(object key) { //用套接字集合的key来调用不同套接字的Receive方法 string keys = key as string ; while (true) { byte[] arrRecMsg = new byte[1024 * 1024 * 2]; int length = -1; try { length = dic[keys].Receive(arrRecMsg); } catch (SocketException ex) { MessageBox.Show(ex.Message); } catch (Exception ex) { MessageBox.Show(ex.Message); } //判断接收的是否是文件 if (arrRecMsg[0] == 0) { string strRecMsg = System.Text.Encoding.UTF8.GetString(arrRecMsg, 1, length-1); ShowMsg(keys + ",客户端发来信息:" + strRecMsg); } else if (arrRecMsg[0] == 1) { SaveFileDialog sfd = new SaveFileDialog(); if (sfd.ShowDialog() == System.Windows.Forms.DialogResult.OK) { string SaveFilePath = sfd.FileName; using (FileStream fs = new FileStream(SaveFilePath, FileMode.Create)) { fs.Write(arrRecMsg, 1, length-1); ShowMsg("保存文件成功!" + SaveFilePath); } } } else { MessageBox.Show("没有接收到数据!"); } } } /// <summary> /// 服务器端发送消息 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void btnSend_Click(object sender, EventArgs e) { //先获取文本中发送的消息 string strMsg = txtSendMsg.Text; //将要发送的数据转换成字节数据 byte[] arrMsg = System.Text.Encoding.UTF8.GetBytes(strMsg); byte[] arrMsgSend = new byte[arrMsg.Length+1]; arrMsgSend[0] = 0; Buffer.BlockCopy(arrMsg, 0, arrMsgSend, 1, arrMsg.Length); //利用连接套接字发送数据 string strClientKey = lbOnline.Text; //或得选中列表中的对应的某个客户端的通信地址 try { dic[strClientKey].Send(arrMsgSend); } catch { MessageBox.Show("请选择要发送的客户端"); } ShowMsg(String.Format("发送消息给{0}:{1}" ,lbOnline.Text,strMsg)); } //群发消息 private void btnSendToAll_Click(object sender, EventArgs e) { string strMsg = txtSendMsg.Text; //字符串转换成字节 byte[] arrMsg = System.Text.Encoding.UTF8.GetBytes(strMsg); //读取全部用于连接的套接字,全部发送消息 foreach (Socket s in dic.Values) { s.Send(arrMsg); } ShowMsg("群发完毕!~~"); } //选择文件的路径 private void btnChooseFile_Click(object sender, EventArgs e) { OpenFileDialog ofd = new OpenFileDialog(); if (ofd.ShowDialog() == System.Windows.Forms.DialogResult.OK) { txtFilePath.Text = ofd.FileName; } } //发送文件 private void btnSendFile_Click(object sender, EventArgs e) { //一使用完就释放内存用using using(FileStream fs=new FileStream(txtFilePath.Text,FileMode.Open))//打开文件的路径和方式 { byte[] arrFile = new byte[1024 * 1024 * 2];//new一个2M的字节数组(缓存区) //将文件读到字节数组中,并得到真实数据的长度 int length=fs.Read(arrFile, 0, arrFile.Length); //新定义个字节数组,存储带标示位的数据 byte[] arrFileSend = new byte[length+1]; arrFileSend[0] = 1;//代表发送的数据是文件 //最简单的方法,利用循环将原数据往后移一位 //for (int i = 0; i < length; i++) //{ // arrFileSend[i + 1] = arrFile[i]; //} //将arrFile从第0个数据拷贝到arrFileSend中,从第1个开始到length长度 Buffer.BlockCopy(arrFile, 0, arrFileSend, 1,length); //选择客户端发送带标志位的数据 dic[lbOnline.Text].Send(arrFileSend); } } /// <summary> /// 文本框的显示 /// </summary> /// <param name="msg"></param> void ShowMsg(string msg) { try { txtMsg.AppendText(msg + "\r\n"); } catch { MessageBox.Show("请选择客户端!"); } } } }
客户端
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using System.Net.Sockets; using System.Net; using System.Threading; using System.IO; namespace 客户端 { public partial class client : Form { public client() { InitializeComponent(); TextBox.CheckForIllegalCrossThreadCalls = false; } Socket socketClient = null; Thread threadRec = null; private void btnConnect_Click(object sender, EventArgs e) { //定义一个套接字,用于连接 IPAddress address = IPAddress.Parse(txtIPadress.Text); IPEndPoint endPoint = new IPEndPoint(address, int.Parse(txtPoint.Text.Trim())); socketClient = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); //连接服务器 if (endPoint == null) { MessageBox.Show("没有可连接的服务器!"); } else { socketClient.Connect(endPoint); } //利用线程接收服务器端发来的消息 threadRec = new Thread(ReceiveMsg); threadRec.IsBackground = true; threadRec.Start(); } /// <summary> /// 用来接收消息的套接字方法 /// </summary> void ReceiveMsg() { while (true) { //接收数据定义的缓存区(2M),字节类型 byte[] arrMsgRec = new byte[1024 * 1024 * 2]; //length是服务器端真正传过来数据的长度(Receive的返回值),Receive接收数据 int length = -1; try { length = socketClient.Receive(arrMsgRec); } catch (SocketException ex) { MessageBox.Show(ex.Message); } catch (Exception ex) { MessageBox.Show(ex.Message); } //判断接收的是否是文件 if (arrMsgRec[0]== 0) { string strRecMsg = System.Text.Encoding.UTF8.GetString(arrMsgRec, 1, length-1); ShowMsg( "服务端发来信息:" + strRecMsg); } else if (arrMsgRec[0] == 1) { SaveFileDialog sfd = new SaveFileDialog(); if (sfd.ShowDialog() == System.Windows.Forms.DialogResult.OK) { string SaveFilePath = sfd.FileName; using (FileStream fs = new FileStream(SaveFilePath, FileMode.Create)) { fs.Write(arrMsgRec, 1, length-1); ShowMsg("保存文件成功!" + SaveFilePath); } } } ////将字节装换成了字符串,只转真正有用的字符 //string strMsgRec = System.Text.Encoding.UTF8.GetString(arrMsgRec,0,length); ////打印出来 //ShowMsg(strMsgRec); } } /// <summary> /// 将接收到信息打印到文本框中 /// </summary> /// <param name="msg"></param> void ShowMsg(string msg) { txtMsg.AppendText(msg + "\r\n"); } //发送消息 private void btnSend_Click(object sender, EventArgs e) { string strSendMsg = txtSendMsg.Text; //将字符串转成网络传送的字节数据 byte[] arrSendMsg = System.Text.Encoding.UTF8.GetBytes(strSendMsg); byte[] arrSend = new byte[arrSendMsg.Length+1]; arrSend[0] = 0; Buffer.BlockCopy(arrSendMsg, 0, arrSend, 1, arrSendMsg.Length); //发送数据 socketClient.Send(arrSend); ShowMsg("我说:" + strSendMsg); } //选择文件路径 private void btnChosseFile_Click(object sender, EventArgs e) { OpenFileDialog ofd = new OpenFileDialog(); if (ofd.ShowDialog() == System.Windows.Forms.DialogResult.OK) { txtFilePath.Text = ofd.FileName; } } //发送文件 private void btnSendFile_Click(object sender, EventArgs e) { //一使用完就释放内存用using using (FileStream fs = new FileStream(txtFilePath.Text, FileMode.Open))//打开文件的路径和方式 { byte[] arrFile = new byte[1024 * 1024 * 2];//new一个2M的字节数组(缓存区) //将文件读到字节数组中,并得到真实数据的长度 int length = fs.Read(arrFile, 0, arrFile.Length); //新定义个字节数组,存储带标示位的数据 byte[] arrFileSend = new byte[length + 1]; arrFileSend[0] = 1;//代表发送的数据是文件 //最简单的方法,利用循环将原数据往后移一位 //for (int i = 0; i < length; i++) //{ // arrFileSend[i + 1] = arrFile[i]; //} //将arrFile从第0个数据拷贝到arrFileSend中,从第1个开始到length长度 Buffer.BlockCopy(arrFile, 0, arrFileSend, 1, length); //选择客户端发送带标志位的数据 socketClient.Send(arrFileSend); } } } }
相关文章推荐
- 黑马程序员-我的入学笔记1-关于C#.net基础
- Socket入门笔记 用TcpClient实现一个简易聊天室
- 黑马程序员-我的入学笔记2-关于类
- 黑马程序员--关于异常的一些笔记总结
- C#简易版Socket聊天室 附源码
- 黑马程序员--关于交通灯的笔记
- 一步一步教您用websocket+nodeJS搭建简易聊天室(2)
- 使用socket.io制做简易WEB聊天室
- 黑马程序员--关于线程的一些笔记总结
- 黑马程序员_关于黑马java班入学测试技术分享<前5题>(一)
- socket.io入门以及简易聊天室Demo的展示
- 黑马程序员_温习 网络编辑一 (个人笔记)摘要(网络概述---网络参考模型---网络传输要素---IP地址---端口----传输协议(UDP -- TCP)---Socket机制 )
- 黑马程序员之C# 学习笔记:关于string与stringbuilder的区别
- 黑马程序员关于数组、冒泡排序法的复习笔记
- 黑马程序员学习笔记——关于readLine()的那些事
- 黑马程序员 —入学笔记《基础知识1》
- 黑马程序员 Socket网络编程--聊天室
- 黑马程序员学习笔记 关于继承
- 黑马程序员--关于银行调度系统的笔记
- 黑马程序员_学习日记67_717ASP.NET(Socket聊天室)