要想持续监听接受消息,就必须调用新的线程来专门负责监听发来的消息,可以参考我都代码解析:
服务端namespace 客户端连接
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
TextBox.CheckForIllegalCrossThreadCalls = false; //关闭跨线程调用
}
Thread watchthread=null;//j将监听套接字定义在类中,方便调用
Dictionary<string,Socket> dict=new Dictionary<string,Socket>();
// 定义字典链表,来存储申请连接用户的IP和端口即套接字信息
Dictionary<string, Socket> dictrec = new Dictionary<string, Socket>();
//定义字典列表,用来存连接客户端的套接字
Socket socketWatch=null;
private void protbtn_Click(object sender, EventArgs e)
{ //创建服务端的监听套接字,参数(使用 的IP寻址协议,使用流式连接,使用TCP协议传输数据)
socketWatch = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
// 获取文本框的IP地址对象。
IPAddress address = IPAddress.Parse(iptxt.Text.Trim());
//创建含有IP和port的网络节点对象
IPEndPoint endpoint=new IPEndPoint(address,int.Parse(prottxt.Text.Trim()));
//将负责监听的套接字绑定到唯一的IP端口上
socketWatch.Bind(endpoint);
//设置监听队列的长度
socketWatch.Listen(10);
//
watchthread = new Thread(WTC);
//给线程委托
watchthread.IsBackground = true;
//绑定后台线程
watchthread.Start();
//线程开始
}
private void showMsg(string p)
{
txtb1.AppendText(p+"\r\n");
}
void WTC()
{
while (true)//持续监听
{
Socket socketconnecttion = socketWatch.Accept();//一旦监听到了请求,返回新的通讯的docket。
//将新生成的IP和端口信息和socket加入到字典的键和值
dict.Add(socketconnecttion.RemoteEndPoint.ToString(),socketconnecttion);
//将连接的客户端IP加入到控件的列表
onlinelist.Items.Add(socketconnecttion.RemoteEndPoint.ToString());
//将远程客户端计算机的IP和端口 添加到onlinelist列表
Thread recThread = new Thread(Rec);
//与客户端建立连接后,持续监听客户端是否发送信息,有新的线程来监听
recThread.IsBackground = true;//后台
recThread.Start(socketconnecttion);//传参,当前生成的socket
showMsg("客户端连接成功!"+socketconnecttion.RemoteEndPoint.ToString()+"\r\n");
}
}
void Rec(object socketconnet)
{
while (true)//持续接收客户端消息
{
Socket socketconnettion = socketconnet as Socket;//强制转换成socket
byte[] arrmsg = new byte[1024 * 1024 * 2];
//定义2M字节序列 ,来接受 用户消息
int length;
length = socketconnettion.Receive(arrmsg);
//接受客户端的消息
if (arrmsg[0] == 0)//判断客户端发来的是文字还是文件 0是文字 1是文件
{
string str = System.Text.Encoding.UTF8.GetString(arrmsg, 1, length);
//将字节序列转换成字符串
showMsg("客户端--->" + str);
}
else
if (arrmsg[0] == 1)//当接受是文件时
{
SaveFileDialog sfd = new SaveFileDialog();
//实例化保存文件对话框
if (sfd.ShowDialog() == System.Windows.Forms.DialogResult.OK)
//当保存成功, 将文件名赋给变量filesavepath
{
string filesavepath = sfd.FileName;
using (FileStream fs = new FileStream(filesavepath, FileMode.Create))//(文件路径,文件模式)
//文件流很占内存,所以用using及时释放
{
fs.Write(arrmsg, 1, length - 1);
showMsg("文件保存成功!"+filesavepath);
}
}
}
}
}
private void btnsend_Click(object sender, EventArgs e)
{
if (string.IsNullOrEmpty(onlinelist.Text))
{
MessageBox.Show("请先选择一个好友");
return;
}
else
{
string str = txtserver.Text.Trim();
//将要发送的字符串转换成utf8对应的字节数组
byte[] arrmsg = System.Text.Encoding.UTF8.GetBytes(str);
string strclientKey = onlinelist.Text;
//通过 键 查询 值(即客户的套接字) 来调用值的send()来发送信息
dict[strclientKey].Send(arrmsg);
//socketconnecttion.Send(arrmsg);
showMsg("服务端:--->" + str + "\r\n");
}
}
private void button1_Click(object sender, EventArgs e)
{ //服务端发送信息
string str = txtserver.Text.Trim();
byte[] byarr = new byte[1024 * 1024 * 2];
byarr = System.Text.Encoding.UTF8.GetBytes(str);
//将字符串转换成字节序列
foreach (Socket s in dict.Values)
{ //遍历群发
s.Send(byarr);
}
showMsg("群发完毕");
}
}
}
————————————————————————————————
客户端:
private void textBox1_TextChanged(object sender, EventArgs e)
{
}
Socket socketclient = null;
Thread recThread = null;
private void protbtn_Click(object sender, EventArgs e)
{
IPAddress address = IPAddress.Parse(iptxt.Text.Trim());
//从文本框获取IP
IPEndPoint endpoint=new IPEndPoint( address,int.Parse(prottxt.Text.Trim()));
//从文本框获取端口或IP
socketclient = new Socket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp);
//连接服务器
socketclient.Connect(endpoint);
//调用线程
recThread = new Thread(RecMsg);
recThread.IsBackground = true;
recThread.Start();
}
void RecMsg()
{
while (true)
{
//定义一个接受用的缓存区(2M字节)
byte[] arrmsgrec = new byte[1024 * 1024 * 2];
//将接受到的消息数据传入arrmsgrec数组,并返回真正接受数据的长度
int length=socketclient.Receive(arrmsgrec);
//将字节序列转化为字符串然(要转换的字节序列,开始位置,转换长度)
string strMsgRec = System.Text.Encoding.UTF8.GetString(arrmsgrec, 0, length);
ShowMsg("服务端-->"+strMsgRec);
}
}
void ShowMsg(string str)
{
//想文本框追加文本
txtb1.AppendText( str + "\r\n");
}
private void btnsend_Click(object sender, EventArgs e)
{//客户端向服务端发送信息。
string str = txtclient.Text.Trim();
byte[] byArr = new byte[1024 * 1024 * 2];
byArr = System.Text.Encoding.UTF8.GetBytes(str);
byte[] byarrsend = new byte[byArr.Length + 1];
byarrsend[0] = 0;//发送文字,字节序列首位赋0;
Buffer.BlockCopy(byArr,0,byarrsend,1,byArr.Length);
socketclient.Send(byarrsend);//发送字符序列
ShowMsg("客户端--->"+str);
}
private void filechoosebtn_Click(object sender, EventArgs e)
{
OpenFileDialog ofd = new OpenFileDialog();//打开文件选择对话框
if (ofd.ShowDialog() == System.Windows.Forms.DialogResult.OK)//判断是否选择文件
{
filepathtxt.Text = ofd.FileName;//在文本框显示文件路径
}
}
private void filesendbtn_Click(object sender, EventArgs e)
{ //发送文件
using (FileStream fs = new FileStream(filepathtxt.Text, FileMode.Open))
{
byte[] arrfile = new byte[1024 * 1024 * 2];
int length = fs.Read(arrfile, 0, arrfile.Length);
byte[] arrsend=new byte[length+1];
arrsend[0] = 1;//第一个为标识为
Buffer.BlockCopy(arrfile,0,arrsend,1,length);
socketclient.Send(arrsend);
}
}
}
}
|