private void WatchConnecting()
{
while (true)
{
try
{
socConnection = socketWatch.Accept();
}
catch (Exception ex)
{
txtMsg.AppendText(ex.Message); //提示套接字监听异常
break;
}
//获取访问客户端的IP
clientIP = (socConnection.RemoteEndPoint as IPEndPoint).Address;
//获取访问客户端的Port
clientPort = (socConnection.RemoteEndPoint as IPEndPoint).Port;
//创建访问客户端的唯一标识 由IP和端口号组成
clientName = "IP: " + clientIP +" Port: "+ clientPort;
lstClients.Items.Add(clientName); //在客户端列表添加该访问客户端的唯一标识
dicSocket.Add(clientName, socConnection); //将客户端名字和套接字添加到添加到数据字典中
selectsendrecmsg();
//创建通信线程
//ThreadStart pts = new ThreadStart(ServerRecMsg);
//Thread thread = new Thread(pts);
//thread.IsBackground = true;
////启动线程
//thread.Start();
//dictThread.Add(socConnection.RemoteEndPoint.ToString(), thread);
txtMsg.AppendText("IP: " + clientIP + " Port: " + clientPort + " 的客户端与您连接成功,现在你们可以开始通信了...\r\n");
}
}
private void selectsendrecmsg()
{
for (int i = 0; i < lstClients.Items.Count; i++)
{
switch (i)
{
case 0:
ThreadStart pts = new ThreadStart(ServerRecMsg);
Thread thread = new Thread(pts);
thread.IsBackground = true;
//启动线程
thread.Start();
break;
case 1:
ThreadStart pta = new ThreadStart(ServerRecMsg1);
Thread thread1 = new Thread(pta);
thread1.IsBackground = true;
//启动线程
thread1.Start();
break;
}
}
}
/// <summary>
/// 发送信息到客户端的方法
/// </summary>
/// <param name="sendMsg">发送的字符串信息</param>
private void ServerSendMsg(string sendMsg)
{
sendMsg = "<CAP>";
//将输入的字符串转换成 机器可以识别的字节数组
byte[] arrSendMsg = Encoding.UTF8.GetBytes(sendMsg);
//向客户端列表选中的客户端发送信息
if (!string.IsNullOrEmpty(lstClients.Text.Trim()))
{
//获得相应的套接字 并将字节数组信息发送出去
dicSocket[lstClients.Text.Trim()].Send(arrSendMsg);
//通过Socket的send方法将字节数组发送出去
txtMsg.AppendText("您在 " + GetCurrentTime() + " 向 IP: " + clientIP + " Port: " + clientPort + " 的客户端发送了:\r\n" + sendMsg + "\r\n");
}
else //如果未选择任何客户端 则默认为群发信息
{
//遍历所有的客户端
for (int i = 0; i < lstClients.Items.Count; i++)
{
dicSocket[lstClients.Items[i].ToString()].Send(arrSendMsg);
}
txtMsg.AppendText("您在 " + GetCurrentTime() + " 群发了信息:\r\n" + sendMsg + " \r\n");
}
}
/// <summary>
/// 接收客户端发来的信息
/// </summary>
private void ServerRecMsg()
{
// NetworkStream stream = new NetworkStream(dicSocket[lstClients.Items[i].ToString()]);
while(true)
{
//Socket socketServer = socketClientPara as Socket;
NetworkStream stream = new NetworkStream(dicSocket[lstClients.Items[0].ToString()]); tempName = filepath + DateTime.Now.ToString("MMddhhmmss") + DateTime.Now.Millisecond.ToString() + ".tmp";
//tempName1 = filepath + DateTime.Now.ToString("MMddhhmmss") + DateTime.Now.Millisecond.ToString() + ".tmp1"; filestream = new FileStream(tempName, FileMode.OpenOrCreate, FileAccess.Write);
int length = 1024; byte[] bye = new byte[1024]; int tt = stream.Read(bye, 0, length); while (tt > 0)
{
string ss = System.Text.Encoding.ASCII.GetString(bye);
int x = ss.IndexOf("<EOF>");
if (x != -1)
{ filestream.Write(bye, 0, x);
filestream.Flush();
break;
}
else
{
filestream.Write(bye, 0, tt);
filestream.Flush();
}
tt = stream.Read(bye, 0, length);
}
filestream.Close();
Thread.Sleep(2000);
Image im = new Bitmap(tempName);
pictureBox1.Image = im;
Control.CheckForIllegalCrossThreadCalls = false;
}
} private FileStream filestream1 = null;
private string filepath1 = "C:\\abc\\";
private string tempName1 = "";
private void ServerRecMsg1()
{
while (true)
{
NetworkStream stream = new NetworkStream(dicSocket[lstClients.Items[1].ToString()]);
tempName1 = filepath1 + DateTime.Now.ToString("MMddhhmmss") + DateTime.Now.Millisecond.ToString() + ".abc";
// tempName1 = filepath + DateTime.Now.ToString("MMddhhmmss") + DateTime.Now.Millisecond.ToString() + ".tmp1";
//string[] tempname = { tempName, tempName1 };
filestream1 = new FileStream(tempName1, FileMode.OpenOrCreate, FileAccess.Write);
int length = 1024; byte[] bye = new byte[1024]; int tt = stream.Read(bye, 0, length); while (tt > 0)
{
string ss = System.Text.Encoding.ASCII.GetString(bye);
int x = ss.IndexOf("<EOF>");
if (x != -1)
{ filestream1.Write(bye, 0, x);
filestream1.Flush();
break;
}
else
{
filestream1.Write(bye, 0, tt);
filestream1.Flush();
}
tt = stream.Read(bye, 0, length);
}
filestream1.Close();
Image im1 = new Bitmap(tempName1);
pictureBox2.Image = im1;
}
}
//将信息发送到到客户端
private void btnSendMsg_Click(object sender, EventArgs e)
{
ServerSendMsg("CAP>");
}
private void chkBOX_CheckedChanged(object sender, EventArgs e)
{
if (chkBOX.Checked)
{
timer.AutoReset = true;
timer.Enabled = true;
timer.Interval = 5000;
timer.Start();
}
else
{
timer.Stop();
}
}
}
}
客户端代码
namespace ChatClient
{
/// <summary>
/// 接受服务端发来信息的方法
/// </summary>
private void RecMsg()
{
while (true) //持续监听服务端发来的消息
{
string strRecMsg = null;
int length = 0;
byte[] buffer = new byte[SendBufferSize];
try
{
//将客户端套接字接收到的字节数组存入内存缓冲区, 并获取其长度
length = socketClient.Receive(buffer);
}
catch (SocketException ex)
{
txtMsg.AppendText("套接字异常消息:" + ex.Message + "\r\n");
txtMsg.AppendText("服务端已断开连接\r\n");
break;
}
catch (Exception ex)
{
txtMsg.AppendText("系统异常消息: " + ex.Message + "\r\n");
break;
}
//将套接字获取到的字节数组转换为人可以看懂的字符串
strRecMsg = Encoding.UTF8.GetString(buffer, 0, length);
if (strRecMsg=="<CAP>")
{
//txtMsg.AppendText("服务端在 " + GetCurrentTime() + " 给您发送了:\r\n" + strRecMsg + "\r\n");
NetworkStream stream = new NetworkStream(socketClient);
transfer(ref stream);
strRecMsg = null;
}
}
}
private void transfer(ref NetworkStream stream)
{
byte[] bb = READBMP();
stream.Write(bb, 0, bb.Length);
bb = new byte[1024];
bb = System.Text.Encoding.ASCII.GetBytes("<EOF>");
stream.Write(bb, 0, bb.Length);
stream.Flush();
stream.Close();
}
private byte[] READBMP()
{
Image bt = ScreenCapture.Capture();
Bitmap sbt = new Bitmap(bt, 1024, 768);
MemoryStream ms = new MemoryStream();
sbt.Save(ms, System.Drawing.Imaging.ImageFormat.Png);
return ms.ToArray();
} ////向服务端发送信息
//private void btnCSend_Click(object sender, EventArgs e)
//{
// ClientSendMsg(txtCMsg.Text, 0);
//}
}
}
private void WatchConnecting()
{
while (true)
{
try
{
socConnection = socketWatch.Accept();
}
catch (Exception ex)
{
txtMsg.AppendText(ex.Message); //提示套接字监听异常
break;
}
//获取访问客户端的IP
clientIP = (socConnection.RemoteEndPoint as IPEndPoint).Address;
//获取访问客户端的Port
clientPort = (socConnection.RemoteEndPoint as IPEndPoint).Port;
//创建访问客户端的唯一标识 由IP和端口号组成
clientName = "IP: " + clientIP +" Port: "+ clientPort;
lstClients.Items.Add(clientName); //在客户端列表添加该访问客户端的唯一标识
dicSocket.Add(clientName, socConnection); //将客户端名字和套接字添加到添加到数据字典中
selectsendrecmsg();
//创建通信线程
//ThreadStart pts = new ThreadStart(ServerRecMsg);
//Thread thread = new Thread(pts);
//thread.IsBackground = true;
////启动线程
//thread.Start();
//dictThread.Add(socConnection.RemoteEndPoint.ToString(), thread);
txtMsg.AppendText("IP: " + clientIP + " Port: " + clientPort + " 的客户端与您连接成功,现在你们可以开始通信了...\r\n");
}
}
private void selectsendrecmsg()
{
for (int i = 0; i < lstClients.Items.Count; i++)
{
switch (i)
{
case 0:
ThreadStart pts = new ThreadStart(ServerRecMsg);
Thread thread = new Thread(pts);
thread.IsBackground = true;
//启动线程
thread.Start();
break;
case 1:
ThreadStart pta = new ThreadStart(ServerRecMsg1);
Thread thread1 = new Thread(pta);
thread1.IsBackground = true;
//启动线程
thread1.Start();
break;
}
}
}
/// <summary>
/// 发送信息到客户端的方法
/// </summary>
/// <param name="sendMsg">发送的字符串信息</param>
private void ServerSendMsg(string sendMsg)
{
sendMsg = "<CAP>";
//将输入的字符串转换成 机器可以识别的字节数组
byte[] arrSendMsg = Encoding.UTF8.GetBytes(sendMsg);
//向客户端列表选中的客户端发送信息
if (!string.IsNullOrEmpty(lstClients.Text.Trim()))
{
//获得相应的套接字 并将字节数组信息发送出去
dicSocket[lstClients.Text.Trim()].Send(arrSendMsg);
//通过Socket的send方法将字节数组发送出去
txtMsg.AppendText("您在 " + GetCurrentTime() + " 向 IP: " + clientIP + " Port: " + clientPort + " 的客户端发送了:\r\n" + sendMsg + "\r\n");
}
else //如果未选择任何客户端 则默认为群发信息
{
//遍历所有的客户端
for (int i = 0; i < lstClients.Items.Count; i++)
{
dicSocket[lstClients.Items[i].ToString()].Send(arrSendMsg);
}
txtMsg.AppendText("您在 " + GetCurrentTime() + " 群发了信息:\r\n" + sendMsg + " \r\n");
}
}
/// <summary>
/// 接收客户端发来的信息
/// </summary>
private void ServerRecMsg()
{
// NetworkStream stream = new NetworkStream(dicSocket[lstClients.Items[i].ToString()]);
while(true)
{
//Socket socketServer = socketClientPara as Socket;
NetworkStream stream = new NetworkStream(dicSocket[lstClients.Items[0].ToString()]); tempName = filepath + DateTime.Now.ToString("MMddhhmmss") + DateTime.Now.Millisecond.ToString() + ".tmp";
//tempName1 = filepath + DateTime.Now.ToString("MMddhhmmss") + DateTime.Now.Millisecond.ToString() + ".tmp1"; filestream = new FileStream(tempName, FileMode.OpenOrCreate, FileAccess.Write);
int length = 1024; byte[] bye = new byte[1024]; int tt = stream.Read(bye, 0, length); while (tt > 0)
{
string ss = System.Text.Encoding.ASCII.GetString(bye);
int x = ss.IndexOf("<EOF>");
if (x != -1)
{ filestream.Write(bye, 0, x);
filestream.Flush();
break;
}
else
{
filestream.Write(bye, 0, tt);
filestream.Flush();
}
tt = stream.Read(bye, 0, length);
}
filestream.Close();
Thread.Sleep(2000);
Image im = new Bitmap(tempName);
pictureBox1.Image = im;
Control.CheckForIllegalCrossThreadCalls = false;
}
} private FileStream filestream1 = null;
private string filepath1 = "C:\\abc\\";
private string tempName1 = "";
private void ServerRecMsg1()
{
while (true)
{
NetworkStream stream = new NetworkStream(dicSocket[lstClients.Items[1].ToString()]);
tempName1 = filepath1 + DateTime.Now.ToString("MMddhhmmss") + DateTime.Now.Millisecond.ToString() + ".abc";
// tempName1 = filepath + DateTime.Now.ToString("MMddhhmmss") + DateTime.Now.Millisecond.ToString() + ".tmp1";
//string[] tempname = { tempName, tempName1 };
filestream1 = new FileStream(tempName1, FileMode.OpenOrCreate, FileAccess.Write);
int length = 1024; byte[] bye = new byte[1024]; int tt = stream.Read(bye, 0, length); while (tt > 0)
{
string ss = System.Text.Encoding.ASCII.GetString(bye);
int x = ss.IndexOf("<EOF>");
if (x != -1)
{ filestream1.Write(bye, 0, x);
filestream1.Flush();
break;
}
else
{
filestream1.Write(bye, 0, tt);
filestream1.Flush();
}
tt = stream.Read(bye, 0, length);
}
filestream1.Close();
Image im1 = new Bitmap(tempName1);
pictureBox2.Image = im1;
}
}
//将信息发送到到客户端
private void btnSendMsg_Click(object sender, EventArgs e)
{
ServerSendMsg("CAP>");
}
private void chkBOX_CheckedChanged(object sender, EventArgs e)
{
if (chkBOX.Checked)
{
timer.AutoReset = true;
timer.Enabled = true;
timer.Interval = 5000;
timer.Start();
}
else
{
timer.Stop();
}
}
}
}
客户端代码
namespace ChatClient
{
/// <summary>
/// 接受服务端发来信息的方法
/// </summary>
private void RecMsg()
{
while (true) //持续监听服务端发来的消息
{
string strRecMsg = null;
int length = 0;
byte[] buffer = new byte[SendBufferSize];
try
{
//将客户端套接字接收到的字节数组存入内存缓冲区, 并获取其长度
length = socketClient.Receive(buffer);
}
catch (SocketException ex)
{
txtMsg.AppendText("套接字异常消息:" + ex.Message + "\r\n");
txtMsg.AppendText("服务端已断开连接\r\n");
break;
}
catch (Exception ex)
{
txtMsg.AppendText("系统异常消息: " + ex.Message + "\r\n");
break;
}
//将套接字获取到的字节数组转换为人可以看懂的字符串
strRecMsg = Encoding.UTF8.GetString(buffer, 0, length);
if (strRecMsg=="<CAP>")
{
//txtMsg.AppendText("服务端在 " + GetCurrentTime() + " 给您发送了:\r\n" + strRecMsg + "\r\n");
NetworkStream stream = new NetworkStream(socketClient);
transfer(ref stream);
strRecMsg = null;
}
}
}
private void transfer(ref NetworkStream stream)
{
byte[] bb = READBMP();
stream.Write(bb, 0, bb.Length);
bb = new byte[1024];
bb = System.Text.Encoding.ASCII.GetBytes("<EOF>");
stream.Write(bb, 0, bb.Length);
stream.Flush();
stream.Close();
}
private byte[] READBMP()
{
Image bt = ScreenCapture.Capture();
Bitmap sbt = new Bitmap(bt, 1024, 768);
MemoryStream ms = new MemoryStream();
sbt.Save(ms, System.Drawing.Imaging.ImageFormat.Png);
return ms.ToArray();
}
////向服务端发送信息
//private void btnCSend_Click(object sender, EventArgs e)
//{
// ClientSendMsg(txtCMsg.Text, 0);
//}
}
}这样看起来比较好点
流程大致是这样的:
while(true)
{
侦听
创建一个线程,全程实现与客户的交互
}
一旦创建了两个线程,就会出现争夺资源的现象。而且还无法干预,因为在子线程里
虽然有连接字列表,但他并没有其作用
正确的做法是:
while(true)
{
从连接字列表中选出当前活跃的连接字
如果是主连接字,则创建用户连接字,保存于连接字列表,并完成首轮应答
如果是用户连接字,完成与之对应的一轮会话
}
Socket.Select 是核心,用不用多线程都无所谓