关于客户端和服务端聊天室的思路和代码(主要参考传智播客讲课)
来源:互联网 发布:中文域名 企业 编辑:程序博客网 时间:2024/06/11 18:40
服务端的代码:
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 ItcastSocketTest{ /// <summary> /// 基本思路一、关于套接字二、关于线程 /// 1.1、客户端要本地的ip和一个socket相关联--通过socketWatch.Bind(endpoint);完成 /// 1.2、完成关联之后就开始用用“第一线程watchTread” 监听 /// 1.3、监听到客户端之后,服务端会再创建一个负责与客户端通信的socket----socketConnetion /// 2.1、客户端与服务端的通信都通过socketConnetion来实现 包括send receive /// 2.2、当服务当接收信息时,要创建一个新的“第二线程recieveTread”,防止冲突 /// 为什么发送不用创建线程 /// 因为发送消息的时间服务器不用对自己监听 当客户端发送消息时, 服务端要对其监听 /// </summary> public partial class Form1 : Form { public Form1() { InitializeComponent(); TextBox.CheckForIllegalCrossThreadCalls = false; } Thread watchTread=null;//创建一个线程,防止线程“死等”事件的发生 Thread recieveTread = null;//创建一个接收线程, Socket socketWatch=null;//创建一个套接字用来获取服务器的ip和端口 Socket socketConnetion = null;//链接成功后返回一个套接字 Dictionary<string,Socket> dtSocket=new Dictionary<string,Socket>();//创建一个字段,用来实现服务端向多个客户端发送信息 Dictionary<string, Thread> dtThread = new Dictionary<string, Thread>();//创建一个字段,用来实现服务端向多个客户端发送信息 /// <summary> /// 启动服务端 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void BtnBeginServer_Click(object sender, EventArgs e) { //创建服务器线程 负责监听的套接字 socketWatch = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); IPAddress address = IPAddress.Parse(txtIP.Text.ToString()); IPEndPoint endpoint = new IPEndPoint(address, int.Parse(txtPort.Text.Trim())); //========================================================= socketWatch.Bind(endpoint);//将负责监听的套接字绑定到指定的ip和端口上 socketWatch.Listen(10); //======================================================= //创建监听线程,防止UI线程与监听线程冲突 watchTread = new Thread(WatchConnection); watchTread.IsBackground = true; watchTread.Start(); //======================================================== //创建客户端向客户端发送消息进程 //clientToClientThread = new Thread(recieveAndSend); //clientToClientThread.IsBackground = false; //clientToClientThread.Start(); MsgShow("服务器监听成功!"); } /// <summary> /// 链接服务端 /// </summary> void WatchConnection() { while(true) { socketConnetion = socketWatch.Accept();//一旦监听成功将返回一个链接套接字 string strClient = socketConnetion.RemoteEndPoint.ToString();//获取远程客户端的ip和port信息 lbClientList.Items.Add(strClient); dtSocket.Add(strClient, socketConnetion); //======================================================= //创建接收消息进程 recieveTread = new Thread(recievInfo);//当服务端接收消息时会和ui线程冲突,新建线程 recieveTread.IsBackground = false; recieveTread.Start(socketConnetion); dtThread.Add(strClient,recieveTread); MsgShow("连接服务器成功!!" + strClient); } } #region 接受消息委托--recievInfo(Object socketpara) /// <summary> /// 接收消息 /// </summary> void recievInfo(Object socketpara) { Socket socketRecieve = socketpara as Socket; while (true) { Byte[] arrMsgRec = new byte[1024 * 1024 * 2]; //用来储存接收服务端的二进制数据 //接收到文件的长度 int length = socketRecieve.Receive(arrMsgRec);//完成了接受传过来的二进制数据,并且返回一个整形数值 if (arrMsgRec[0] == 0) { //把接收到的消息转化成string类型 string strMsgRec = System.Text.Encoding.UTF8.GetString(arrMsgRec, 1, length); MsgShow(strMsgRec); } else if (arrMsgRec[0] == 1) { SaveFileDialog sfd = new SaveFileDialog(); if (sfd.ShowDialog(this) == DialogResult.OK) { string fileSavePath = sfd.FileName; using (FileStream fs = new FileStream(fileSavePath, FileMode.Create)) { fs.Write(arrMsgRec, 1, length - 1); MsgShow("文件已经保存在:" + fileSavePath); } } } } } #endregion void MsgShow(string str) { txtMsg.AppendText(str + "\r\n"); } private void btnSend_Click(object sender, EventArgs e) { string strMsg=txtSend.Text.Trim(); byte[] arrMsg=System.Text.Encoding.UTF8.GetBytes(strMsg); //==================================================================== //找到选中客户端,让字典中的key值与选中客户端的名字相同,则向他发送消息 string strClient = lbClientList.Text; dtSocket[strClient].Send(arrMsg); MsgShow(strMsg + "已发送!"); } private void btnSendToAll_Click(object sender, EventArgs e) { string strMsg = txtSend.Text.Trim(); byte[] arrMsg = System.Text.Encoding.UTF8.GetBytes(strMsg); foreach (Socket s in dtSocket.Values) { s.Send(arrMsg); } MsgShow("群发完毕~~"); } }}
客户端代码:
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 ChatClient{ public partial class FClient : Form { public FClient() { InitializeComponent(); //防止出现不运行的txtMsg线程操作 TextBox.CheckForIllegalCrossThreadCalls = false; } Socket socketClient; private void BtnConntionServer_Click(object sender, EventArgs e) { socketClient = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); IPAddress address = IPAddress.Parse(txtIP.Text.ToString()); IPEndPoint endpoint = new IPEndPoint(address, int.Parse(txtPort.Text.Trim())); socketClient.Connect(endpoint); Thread recThread = new Thread(RecMsg); recThread.IsBackground = false;//防止在关闭程序后另外一个线程还在进行 recThread.Start();//出现一个实例,一定要让其start 说明是线程可以开始了即就绪了 } void RecMsg() { while(true) { Byte[] arrMsgRec = new byte[1024 * 1024 * 2]; //用来储存接收服务端的二进制数据 //接收到文件的长度 int length=socketClient.Receive(arrMsgRec); //把接收到的消息转化成string类型 string strMsgRec = System.Text.Encoding.UTF8.GetString(arrMsgRec, 0, length); MsgShow(strMsgRec); } } void MsgShow(string str) { txtMsg.AppendText(str + "\r\n"); } private void btnSend_Click(object sender, EventArgs e) {//先与主机建立链接,然后让主机产生一个负责通讯的套接字,最终由客户端send,服务端recieve就可以 //socketClient = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); //IPAddress address = IPAddress.Parse(txtIP.Text.ToString()); //IPEndPoint endpoint = new IPEndPoint(address, int.Parse(txtPort.Text.Trim())); //socketClient.Connect(endpoint); string msg = this.txtC2S.Text.Trim(); byte[] arrMsg = System.Text.Encoding.UTF8.GetBytes(msg); byte[] arrMsgSend = new byte[arrMsg.Length + 1]; arrMsgSend[0] = 0; Buffer.BlockCopy(arrMsg, 0, arrMsgSend, 1, arrMsg.Length); socketClient.Send(arrMsgSend); MsgShow("已经将"+msg+"发送到服务端"); } private void btnChoiceFile_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(FileStream fs=new FileStream(txtFilePath.Text,FileMode.Open)) { byte[] arrFile = new byte[1024 * 1024 * 2]; int length = fs.Read(arrFile, 0, arrFile.Length); byte[] arrFileSend = new byte[length + 1]; arrFileSend[0] = 1; Buffer.BlockCopy(arrFile, 0, arrFileSend,1, length ); socketClient.Send(arrFileSend); MsgShow("传送成功!"); } } }}
- 关于客户端和服务端聊天室的思路和代码(主要参考传智播客讲课)
- 实现聊天室的思路 和部分代码
- 聊天室的服务端和客户端实现多人聊天
- JMX服务端和客户端的代码
- net Winform socket 套接字聊天室客户端和服务端 源码
- net Winform socket 套接字聊天室客户端和服务端 源码
- 聊天室初步代码(socket客户端和服务器端源代码)~
- Android上传图片到服务器的代码怎么写(Android客户端代码和服务端代码)
- Java NIO客户端和服务端(聊天室:单聊,群聊,服务端广播消息,上线以及上线人数通知,下线通知)
- 简单的Android服务端和客户端登录交互(服务端)
- 简单实用的java socket服务端和客户端代码
- 用thrift实现客户端和服务端的C++代码
- Android图片上传的客户端和服务端代码
- 关于客户端和服务端通信方式的一些实验
- Socket编程服务端和客户端代码
- Mina客户端和服务端代码编写
- java NIO服务端和客户端代码实现
- 聊天程序服务端和客户端代码分享
- android Broadcast 生命周期详细分析
- mini6410基于linux2.6.36内核制作initramfs文件系统
- 很炫的Adobe Flex的展示案例地址
- 系统“不幸”需要重装时应该备份什么?
- MPI学习笔记——点对点通信
- 关于客户端和服务端聊天室的思路和代码(主要参考传智播客讲课)
- Bootstrap---Fluid layout 流布局
- apache2.0+resin3.16pro 集群 session同步
- VM Esx 5 虚拟机安装
- java连接数据库的Connection中的prepareStatement与createStatement的区别
- Linux下Apache的安装
- 基于A*算法的八数码问题(九宫问题)解法的程序实现(新增有无解判断)
- BitBlt用法
- 想成为架构师