using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace Socket服务端
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
//存储客户端IP与Socket的键值对集合
Dictionary<string, Socket> dicSocket = new Dictionary<string, Socket>();
/// <summary>
/// 开始监听按钮
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void button1_Click(object sender, EventArgs e)
{
try
{
//1.创建一个监听的Socket
Socket socketWatch = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
//2.创建IP地址和端口号对象
IPAddress ip = IPAddress./*Any;//*/Parse(textIP.Text);
IPEndPoint point = new IPEndPoint(ip, Convert.ToInt32(textPort.Text));
//3.让负责监听的Socket绑定IP以及端口号
socketWatch.Bind(point);
ShowMdg("监听成功");
//4.监听队列
socketWatch.Listen(10);
//5.创建负责监听的Socket,来接受客户端的连接, 创建与客户端通信的Socket (需要在子线程中循环执行)
Thread th = new Thread(Listen);
th.IsBackground = true;
th.Start(socketWatch);
}
catch
{ }
}
/// <summary>
///监听方法
/// </summary>
/// <param name="o">主进程中创建的负责监听的Socket以object形式传入</param>
private void Listen(object o)
{
//转为Socket类的对象(里式转换)
Socket socketWatch = o as Socket;
while (true)//循环监听客户端的接入,为其创建负责与之通信的Socket对象,并以IP,Socket对象的键值对形式将其加入列表
{
try
{
Socket socketSend = socketWatch.Accept();//5.次方法会一直等待客户端进行连接需在子线程中执行
dicSocket.Add(socketSend.RemoteEndPoint.ToString(), socketSend);//客户端连接到服务器时将其IP地址与负责通信的Socket存入字典集合
//将远程客户端的IP地址端口号存到下拉菜单中
comboBox1.Items.Add(socketSend.RemoteEndPoint.ToString());
ShowMdg(socketSend.RemoteEndPoint.ToString() + "连接成功");//显示远程客户端及端口号
//6.客户端连接成功后,服务器接收客户端发来的消息 (子线程中循环执行)
Thread th = new Thread(Receive);
th.IsBackground = true;
th.Start(socketSend);
}catch
{ }
}
}
/// <summary>
/// 服务器端不停接收客户端发来的消息
/// </summary>
/// <param name="o">子线程中创建的负责与此客户端收发数据的Socket对象</param>
private void Receive(object o)
{
Socket socketSend = o as Socket;
while (true)//不断接受客户端发来的消息
{
try
{
byte[] date = new byte[1024 * 1024 * 2];//字节数组容器:接收发来的消息
int r = socketSend.Receive(date);
if (r == 0)//客户端退出收到的字节数为0时结束循环,不再接收此客户端消息
break;
string s = Encoding.UTF8.GetString(date, 0, r);
ShowMdg(socketSend.RemoteEndPoint.ToString() + ":" + s);
}
catch
{ }//为空:出现异常时不进行反馈
}
}
private void ShowMdg(string date)
{
textLog.AppendText(date + "\r\n");
}
private void Form1_Load(object sender, EventArgs e)
{
Control.CheckForIllegalCrossThreadCalls=false;//取消跨线程检测
}
/// <summary>
/// 服务器向客户端发送消息
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void btn_Send_Click(object sender, EventArgs e)
{
string message = textMsg.Text;//向客户端传输的信息
byte[] data = Encoding.UTF8.GetBytes(message);//对一个字符串做编码,转为字节数组
//获取用户在下拉菜单中选中的IP地址(服务器给指定客户端发送消息)
string ip = comboBox1.SelectedItem.ToString();
dicSocket[ip].Send(data);
//向每个客户端发送消息
/*foreach (KeyValuePair<string ,Socket> soc in dicSocket)
{
soc.Value.Send(data);
}*/
}
}
}