监听c tcp实现多个客户端与服务端数据与文件的传输

ja**文件传输  时间:2021-01-12  阅读:()

C#菜鸟做这个东东竟然花了快三天的时间了 真是菜菜菜下面是我用C#写的一个简单的TCP通信 主要的功能有

1 多个客户端与服务器间的数据交流

2可以实现群发的功能

3客户端与服务端可以进行文件的传输

主要用到的知识 TCP里的 socket 、 、 、 多线程Thread 、 、 、

下面的是界面

下面分别是服务端和客户端的代码如若借用 请标明出处~~~服务端代码

[csharp]view plaincopyprint?using System;using System.Col lections.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;//IP IPAddress, IPEndPoint 端口等using System.Threading;using System.IO;namespace_11111

{publ ic partial class frm_server :Form

{publ icfrm_server()

{

Initial izeComponent();

TextBox.CheckForIl legalCrossThreadCal ls=false;

}

Thread threadWatch=nul l ;// 负责监听客户端连接请求的线程

Socket socketWatch=nul l ;

Dictionary<string,Socket>dict=new Dictionary<string,Socket>();

Dictionary<string,Thread>dictThread=new Dictionary<string,Thread>();private void btnBeginListen_Cl ick(object sender,EventArgs e)

{

//创建负责监听的套接字 注意其中的参数socketWatch = new Socket(AddressFami ly.InterNetwork, SocketType.Stream,ProtocolType.Tcp);

//获得文本框中的IP对象

IPAddress address=IPAddress.Parse(txtIp.Text.Trim());

//创建包含ip和端口号的网络节点对象

IPEndPoint endPoint=new IPEndPoint(address, int.Parse(txtPort.Text.Trim()));t ry

{

//将负责监听的套接字绑定到唯一的ip和端口上socketWatch.Bind(endPoint);

}catch(SocketException se)

{

MessageBox.Show("异常 "+se.Message);return;

}

//设置监听队列的长度socketWatch.Li sten(10);

//创建负责监听的线程threadWatch=new Thread(WatchConnecting);threadWatch.IsBackground=true;threadWatch.Start();

ShowMsg("服务器启动监听成功 ");

//}

}

///<summary>

///监听客户端请求的方法

///</summary>voidWatchConnecting()

{while(true)//持续不断的监听客户端的连接请求

{

//开始监听客户端连接请求 Accept方法会阻断当前的线程

Socket sokConnection=socketWatch.Accept();//一旦监听到一个客户端的请求就返回一个与该客户端通信的套接字

//想列表控件中添加客户端的IP信息lbOnline.Items.Add(sokConnection.RemoteEndPoint.ToString());

//将与客户端连接的套接字对象添加到集合中dict.Add(sokConnection.RemoteEndPoint.ToString(), sokConnection);

ShowMsg("客户端连接成功 ");

Thread thr=new Thread(RecMsg);thr.IsBackground=true;thr.Start(sokConnection);dictThread.Add(sokConnection.RemoteEndPoint.ToString(), thr); //将新建的线程 添加到线程的集合中去。

}

}void RecMsg(object sokConnectionparn)

{

Socket sokCl ient=sokConnectionparn as Socket;while(true)

{

//定义一个2M的缓存区byte[]arrMsgRec=new byte[1024*1024*2];

//将接受到的数据存入到输入arrMsgRec中int length=-1 ;t ry

{length=sokCl ient.Receive(arrMsgRec);//接收数据 并返回数据的长度

}catch(SocketException se)

{

ShowMsg("异常 "+se.Message);

//从通信套接字 集合中删除被中断连接的通信套接字dict.Remove(sokClient.RemoteEndPoint.ToString());

//从通信线程集合中删除被中断连接的通信线程对象dictThread.Remove(sokClient.RemoteEndPoint.ToString());

//从列表中移除被中断的连接IP lbOnline.Items.Remove(sokClient.RemoteEndPoint.ToString());break;

}catch(Exception e)

{

ShowMsg("异常 "+e.Message);

//从通信套接字 集合中删除被中断连接的通信套接字dict.Remove(sokClient.RemoteEndPoint.ToString());

//从通信线程集合中删除被中断连接的通信线程对象dictThread.Remove(sokClient.RemoteEndPoint.ToString());

//从列表中移除被中断的连接IP lbOnline.Items.Remove(sokClient.RemoteEndPoint.ToString());break;

}if(arrMsgRec[0]==0)//表示接收到的是数据

{string strMsg= System.Text.Encoding.UTF8.GetString(arrMsgRec,1, length-1);//将接受到的字节数据转化成字符串

ShowMsg(strMsg);

}if(arrMsgRec[0]==1)//表示接收到的是文件

{

SaveFi leDialog sfd=new SaveFi leDialog();if(sfd.ShowDialog(this)==System.Windows.Forms.DialogResult.OK)

{//在上边的 sfd.ShowDialog  的括号里边一定要加上this否则就不会弹出 另存为 的对话框 而弹出的是本类的其他窗口  这个一定要注意   【解释 加了 this 的sfd.ShowDialog(this)  “另存为”窗口的指针才能被SaveFi leDialog 的对象调用 若不加thisSaveFi leDialog的对象调用的是本类的其他窗口了 当然不弹出“另存为”窗口。】stringfi leSavePath=sfd.Fi leName;//获得文件保存的路径

//创建文件流 然后根据路径创建文件using(Fi leStream fs=new Fi leStream(fileSavePath,Fi leMode.Create))

{fs.Write(arrMsgRec, 1, length- 1);

ShowMsg("文件保存成功 "+fi leSavePath);

}

}

}

}

}void ShowMsg(string str)

{txtMsg.AppendText(str+"\r\n");

}

//发送消息

private void btnSend_Cl ick(object sender,EventArgs e)

{string strMsg="服务器"+"\r\n"+" -->"+txtMsgSend.Text.Trim()+"\r\n";byte[] arrMsg= System.Text.Encoding.UTF8.GetBytes(strMsg); //将要发送的字符串转换成Utf-8字节数组byte[]arrSendMsg=new byte[arrMsg.Length+1];arrSendMsg[0]=0;//表示发送的是消息数据

Buffer.BlockCopy(arrMsg,0,arrSendMsg, 1,arrMsg.Length);string strKey="";strKey=lbOnline.Text.Trim();if(string.IsNullOrEmpty(strKey))//判断是不是选择了发送的对象

{

MessageBox.Show("请选择你要发送的好友   ");

}else

{dict[strKey].Send(arrSendMsg);//解决了 sokConnection是局部变量不能再本函数中引用的问题

ShowMsg(strMsg);txtMsgSend.Clear();

}

}

///<summary>

///群发消息

///</summary>

///<param name="sender"></param>

///<param name="e">消息</param>private void btnSendToAl l_Cl ick(object sender,EventArgs e)

{string strMsg="服务器"+"\r\n"+" -->"+txtMsgSend.Text.Trim()+"\r\n";byte[] arrMsg= System.Text.Encoding.UTF8.GetBytes(strMsg); //将要发送的字符串转换成Utf-8字节数组using System;using System.Col lections.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; //IP IPAddress, IPEndPoint 端口等using System.Threading;

using System.IO;namespace_11111

{publ ic partial class frm_server :Form

{publ icfrm_server()

{

Initial izeComponent();

TextBox.CheckForIl legalCrossThreadCal ls=false;

}

Thread threadWatch=nul l ;// 负责监听客户端连接请求的线程

Socket socketWatch=nul l ;

Dictionary<string,Socket>dict=new Dictionary<string,Socket>();

Dictionary<string,Thread>dictThread=new Dictionary<string,Thread>();private void btnBeginListen_Cl ick(object sender,EventArgs e)

{

//创建负责监听的套接字 注意其中的参数socketWatch=new Socket(AddressFami ly.InterNetwork, SocketType.Stream,ProtocolType.Tcp);

//获得文本框中的IP对象

IPAddress address=IPAddress.Parse(txtIp.Text.Trim());

//创建包含ip和端口号的网络节点对象

IPEndPoint endPoint = new IPEndPoint(address,int.Parse(txtPort.Text.Trim()));t ry

{

//将负责监听的套接字绑定到唯一的ip和端口上socketWatch.Bind(endPoint);

}catch(SocketException se)

{

MessageBox.Show("异常 "+se.Message);return;

}

//设置监听队列的长度socketWatch.Li sten(10);

//创建负责监听的线程threadWatch=new Thread(WatchConnecting);threadWatch.IsBackground=true;threadWatch.Start();

ShowMsg("服务器启动监听成功 ");

//}

}

///<summary>

///监听客户端请求的方法

///</summary>voidWatchConnecting()

{while(true) //持续不断的监听客户端的连接请求

{

//开始监听客户端连接请求 Accept方法会阻断当前的线程

Socket sokConnection=socketWatch.Accept(); //一旦监听到一个客户端的请求 就返回一个与该客户端通信的套接字

//想列表控件中添加客户端的IP信息lbOnline.Items.Add(sokConnection.RemoteEndPoint.ToString());

//将与客户端连接的套接字对象添加到集合中dict.Add(sokConnection.RemoteEndPoint.ToString(), sokConnection);

ShowMsg("客户端连接成功 ");

Thread thr=new Thread(RecMsg);thr.IsBackground=true;thr.Start(sokConnection);dictThread.Add(sokConnection.RemoteEndPoint.ToString(), thr); //将新建的线程添加到线程的集合中去。

}

}void RecMsg(object sokConnectionparn)

{

Socket sokCl ient=sokConnectionparn as Socket;while(true)

{

//定义一个2M的缓存区byte[]arrMsgRec=new byte[1024*1024*2];

//将接受到的数据存入到输入 arrMsgRec中int length=-1 ;t ry

{length=sokCl ient.Receive(arrMsgRec);//接收数据 并返回数据的长度

}catch(SocketException se)

{

ShowMsg("异常 "+se.Message);

//从通信套接字 集合中删除被中断连接的通信套接字dict.Remove(sokClient.RemoteEndPoint.ToString());

//从通信线程集合中删除被中断连接的通信线程对象dictThread.Remove(sokClient.RemoteEndPoint.ToString());

//从列表中移除被中断的连接IP lbOnline.Items.Remove(sokClient.RemoteEndPoint.ToString());break;

}catch(Exception e)

{

ShowMsg("异常 "+e.Message);

//从通信套接字 集合中删除被中断连接的通信套接字dict.Remove(sokClient.RemoteEndPoint.ToString());

//从通信线程集合中删除被中断连接的通信线程对象dictThread.Remove(sokClient.RemoteEndPoint.ToString());

//从列表中移除被中断的连接IP lbOnline.Items.Remove(sokClient.RemoteEndPoint.ToString());break;

}if(arrMsgRec[0]==0) //表示接收到的是数据

{string strMsg =System.Text.Encoding.UTF8.GetString(arrMsgRec,1, length-1);//将接受到的字节数据转化成字符串

ShowMsg(strMsg);

}if(arrMsgRec[0]==1)//表示接收到的是文件

{

SaveFi leDialog sfd=new SaveFi leDialog();if (sfd.ShowDialog(this) ==System.Windows.Forms.DialogResult.OK)

{//在上边的sfd.ShowDialog  的括号里边一定要加上this否则就不会弹出 另存为 的对话框而弹出的是本类的其他窗口 这个一定要注意  【解释加了 this的sfd.ShowDialog(this)  “另存为”窗口的指针才能被SaveFi leDialog的对象调用若不加thisSaveFi leDialog的对象调用的是本类的其他窗口了当然不弹出“另存为”窗口。】string fi leSavePath=sfd.Fi leName;//获得文件保存的路径

//创建文件流 然后根据路径创建文件using (Fi leStream fs = new Fi leStream(fi leSavePath,Fi leMode.Create))

{

华为云年中聚惠618活动,新用户专区,云服务器低至88元/年,3年仅580.98元,热销抢购中,最后2天!

华为云怎么样?华为云用在线的方式将华为30多年在ICT基础设施领域的技术积累和产品解决方案开放给客户,致力于提供稳定可靠、安全可信、可持续创新的云服务,做智能世界的“黑土地”,推进实现“用得起、用得好、用得放心”的普惠AI。华为云作为底座,为华为全栈全场景AI战略提供强大的算力平台和更易用的开发平台。本次年终聚惠618活动相当给力,1核2G内存1m云耀云服务器仅88元/年起,送主机安全基础版套餐,...

licloud:$39/月,香港物理服务器,30M带宽,e3-1230v3/16G内存/1T硬盘

licloud官方消息:当前对香港机房的接近100台物理机(香港服务器)进行打折处理,30Mbps带宽,低至不到40美元/月,速度快,性价比高,跑绝大多数项目都是绰绰有余了。该款香港服务器自带启动、关闭、一键重装功能,正常工作日内30~60分钟交货(不包括非工作日)。 官方网站:https://licloud.io 特价香港物理服务器 CPU:e3-1230v2(4核心、8线程、3.3GH...

IMIDC日本多IP服务器$88/月起,E3-123x/16GB/512G SSD/30M带宽

IMIDC是一家香港本土运营商,商家名为彩虹数据(Rainbow Cloud),全线产品自营,自有IP网络资源等,提供的产品包括VPS主机、独立服务器、站群独立服务器等,数据中心区域包括香港、日本、台湾、美国和南非等地机房,CN2网络直连到中国大陆。目前主机商针对日本独立服务器做促销活动,而且提供/28 IPv4,国内直连带宽优惠后每月仅88美元起。JP Multiple IP Customize...

ja**文件传输为你推荐
虚机虚拟主机一个一年多少钱免费云主机有永久的免费云主机么台湾主机台湾的第一台电脑免费网站空间免费个人网站 空间重庆网站空间重庆建网站的公司 我司准备建一个好点的网站,求推荐虚拟主机管理系统什么虚拟主机管理系统支持W和linux操作系统论坛虚拟主机虚拟主机禁止放论坛淘宝虚拟主机请问在淘宝的代购国外虚拟主机可以买吗?台湾虚拟主机香港虚拟主机和台湾虚拟主机比较,哪个更好!?二级域名什么是一级域名和二级域名以及三级域名
enzu 视频存储服务器 天猫双十一抢红包 一点优惠网 100x100头像 北京双线机房 宁波服务器 1g内存 阿里云官方网站 百度云加速 免费ftp 免费php空间 supercache 云销售系统 双十二促销 cc加速器 回程 瓦工招聘 电脑主机打不开 代理服务器是什么 更多