在开发Soket通信过程中会遇到各种的通信阻塞问题,这里写了一个Soket通信程序,可以在这个基础之上进行改进,这里面包含了客服端与服务端的对话和文件发送功能,请看如下:
这是我新建的三个窗体,窗体Form1是服务端,窗体Form2和窗体Form3是客户端。这里如果需要运行测试的话不知道怎样填IP地址和端口,打开cmd窗口输入ipconfig/all和netstat命令,这两个命令里有你电脑的多个端口号和IP地址,自己输入进行测试,
下面我们来看服务端(Form1)的代码:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
Dictionary<string, Socket> dic = new Dictionary<string, Socket> { };//定义一个集合 储存客户信息
private void Form1_Load(object sender, EventArgs e)
{
Control.CheckForIllegalCrossThreadCalls = false;
Form2 form2 = new Form2();
form2.Show();
}
void ShowMsg(string msg) //监听消息
{
listBox1.Items.Add(msg + "\r\n");
}
private void button1_Click(object sender, EventArgs e)
{
try
{
button1.Enabled = false;
Socket socketWatch = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
IPAddress ip = IPAddress.Any;
//创建对象端口
IPEndPoint point = new IPEndPoint(ip, int.Parse(textBox2.Text));
//绑定端口号
socketWatch.Bind(point);
ShowMsg("监听成功!");
socketWatch.Listen(10);//设置监听
//创建监听线程
Thread thread = new Thread(Listen);
thread.IsBackground = true;
thread.Start(socketWatch);
}catch(Exception ex)
{
MessageBox.Show(ex.ToString());
}
}
//等待客户端的连接,并且创建与之通信的Socket
Socket socketSend;
void Listen(object o)
{
try
{
Socket socketWatch = o as Socket;
while (true)
{
socketSend = socketWatch.Accept();//等待接收客户端连接
ShowMsg(socketSend.RemoteEndPoint.ToString() + ":连接成功"); //添加到用户集里
dic.Add(socketSend.RemoteEndPoint.ToString(), socketSend); //用户IP地址和端口号
listBox2.Items.Add(socketSend.RemoteEndPoint.ToString());
//开起一个新线程 执行接收方法
Thread r_thread = new Thread(Recive);
r_thread.Start(socketSend);
}
}
catch(Exception ex)
{
MessageBox.Show(ex.ToString());
}
}
//服务器不停的接收客户端发来的消息
void Recive(object o)
{
try
{
Socket socketSend = o as Socket;
while (true)
{
//客户端连接服务器成功后 服务器接收客户端发来的消息
byte[] buffer = new byte[1024 * 1024 * 3];
//实际接收到的有效字节数
int len = socketSend.Receive(buffer);
if (len == 0)
{
break;
}
else
{
string sy = Encoding.Unicode.GetString(buffer, 0, len);
ShowMsg(socketSend.RemoteEndPoint.ToString() +":"+ sy);
}
}
}catch(Exception ex)
{
MessageBox.Show(ex.ToString());
}
}
//服务器向客户端发送消息
void send(String ms) //单个发送
{
try
{
byte[] buffer = Encoding.Unicode.GetBytes(ms);
String l = listBox2.SelectedItem.ToString();
dic[l].Send(buffer);
ShowMsg(dic[l].RemoteEndPoint.ToString() + ":" + ms);
}
catch(Exception ex) {
MessageBox.Show("未检测到客户端的连接"+ex);
}
}
private void button2_Click(object sender, EventArgs e)
{
send(textBox3.Text);
this.textBox3.Clear();
}
private void button3_Click(object sender, EventArgs e)
{
try
{
button1.Enabled = true;
socketSend.Shutdown(SocketShutdown.Both);
socketSend.Close();
}catch
{
}
}
String safi; //文件名
private void button4_Click(object sender, EventArgs e)
{
FolderBrowserDialog folderBrowserDialog = new FolderBrowserDialog();
if (folderBrowserDialog.ShowDialog() == DialogResult.OK)
{
textBox4.Text = folderBrowserDialog.SelectedPath; //获取用户选中的路径
safi = Path.GetFileNameWithoutExtension(textBox4.Text);
}
}
private void button5_Click(object sender, EventArgs e)
{
try
{
int a = 0;
NetworkStream NS = new NetworkStream(socketSend); //创建网络流
FileStream FS = new FileStream(textBox4.Text, FileMode.Open, FileAccess.Read); //创建文件流
byte[] sendBytes = new byte[a];
while ((a = FS.Read(sendBytes, 0, sendBytes.Length)) != 0)
{
NS.Write(sendBytes, 0, sendBytes.Length); //向客户端发送流
ShowMsg("文件" + safi + "发送成功!");
}
}
catch(Exception ex) { MessageBox.Show(ex.ToString()); }
}
public void sendsum(string ad) { //批量发送
for (int i = 0; i < listBox2.Items.Count; i++)
{
byte[] bt = Encoding.Unicode.GetBytes(ad);
string sum = listBox2.Items[i].ToString();
dic[sum].Send(bt);
ShowMsg(dic[sum].RemoteEndPoint.ToString() + ":" + ad);
}
}//批量发送
private void button6_Click(object sender, EventArgs e)
{
try
{
sendsum(textBox3.Text.Trim());
}
catch
{
MessageBox.Show("具体原因位:" );
}
}
}
这里我定义了五个方法:第一个方法是showMsg()方法:这里我主要是用它来储存消息列表,显示给用户观看是否消息接收或者发送到位。第二个方法是Listen()方法:这个我是用来等到客户端连接,如果有客户端连接就创建通信通道。第三个方法是Recive()方法:用来不停的接收客户端发来的消息。第四个方法是send()方法:它是用来像客户端发送消息的,就比如客户端向我们发送了消息,我们需要回消息就调用send()方法。第五个方法为sendsum()用来批量发送消息的。
下面我们看客户端的代码(Form2)如下:
public Form2()
{
InitializeComponent();
}
Socket socketSend;
private void button1_Click(object sender, EventArgs e)
{
try
{
button1.Enabled = false;
//创建客户端Socket 获得远程服务器IP和端口号
socketSend = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
IPAddress ip = IPAddress.Parse(textBox1.Text);
IPEndPoint point = new IPEndPoint(ip, int.Parse(textBox2.Text));
socketSend.Connect(point); //建立连接
showMsg("连接成功!");
textBox4.Text = socketSend.RemoteEndPoint.ToString();
//开启新的线程 不停的接收来自服务器的消息
Thread c_thread = new Thread(Recive);
c_thread.IsBackground = true;
c_thread.Start();
}catch(Exception ex)
{
MessageBox.Show(ex.ToString());
}
}
// 接收服务端返回的消息
void Recive()
{
while (true)
{
try
{
byte[] buffer = new byte[1024 * 1024 * 3];
//实际接收到的有效字节
int len = socketSend.Receive(buffer);
if (len == 0) break;
String str = Encoding.Unicode.GetString(buffer, 0, len);
showMsg(socketSend.RemoteEndPoint.ToString() + ":" + str);
}catch(Exception ex)
{
MessageBox.Show(ex.ToString());
}
}
}
//监听消息
void showMsg(string s)
{
listBox1.Items.Add( s+"\r\n");
}
private void button2_Click(object sender, EventArgs e)
{
//发送消息到服务端
try
{
string msg = textBox3.Text.Trim();
byte[] buffer = new byte[1024 * 1024 * 3];
buffer = Encoding.Unicode.GetBytes(msg);
socketSend.Send(buffer);
showMsg("本机" + socketSend.RemoteEndPoint.ToString() + ":" + msg);
}
catch
{
MessageBox.Show("已与服务器断开连接");
}
this.textBox3.Clear();
}
private void Form2_Load(object sender, EventArgs e)
{
Form3 form3 = new Form3();
form3.Show();
Control.CheckForIllegalCrossThreadCalls = false;
//byte[] ReceiveBytes=new byte[];
//int sum=socketSend.Receive()
//NetworkStream NS = new NetworkStream(socketSend);
//String path = @"E:\";
//FileStream FS = new FileStream(path,FileMode.Append);
//byte[] readBytes = new byte[1024 * 3];
//readBytes = NS.Read(, 0, readBytes.Length);
//while (true)
//{
//}
//int a;
//byte[] bytes = new byte[1024 * 3 * 1024];
//NetworkStream NK = new NetworkStream(socketSend);
//FileStream FS = new FileStream(@"D:\Program Files", FileMode.OpenOrCreate, FileAccess.Write);
//while (true)
//{
// FS.Read(bytes, 0, bytes.Length);
//}
}
private void button3_Click(object sender, EventArgs e)
{
try
{
button1.Enabled = true;
socketSend.Shutdown(SocketShutdown.Both);
socketSend.Close();
showMsg("连接已关闭");
}
catch { }
}
private void button4_Click(object sender, EventArgs e)
{
FolderBrowserDialog folderBrowserDialog = new FolderBrowserDialog();
if (folderBrowserDialog.ShowDialog() == DialogResult.OK)
{
textBox4.Text = folderBrowserDialog.SelectedPath; //获取用户选中路径
}
}
private void button5_Click(object sender, EventArgs e)
{
}
}
这里面我写了两个方法一个接收消息,一个监听消息储存到消息列表,以上代码如果有不懂的可以私信我或者需要这份源码的私信我。