以服务端为例,建立通信的步骤:
1、创建代表本机的节点对象:包括ip和port
2、创建负责监听的socket
3、在线程池中为负责监听的socket启用一个线程
4、接受客户端的一个连接,创建负责通信的socket
5、在线程池中为通信socket启用一个线程
6、用通信socket接收客户端发来的信息
7、向客户端发送消息
服务器端代码:
namespace ChatSerivce
{
public delegate void TxtDel(string txt);
public partial class ServiceFrm : Form
{
List<Socket> clientSocketList = new List<Socket>();//与客户端通信的Socket的集合
private TxtDel SetTextDel;
public ServiceFrm()
{
InitializeComponent();
this.SetTextDel = SetTextForTxtHistory;
}
private void btnStart_Click(object sender, EventArgs e)
{
string ip = txtIP.Text;
IPAddress ipAddress = IPAddress.Parse(ip);
//1、创建代表本机的节点对象:包括ip和port
IPEndPoint ipEndPoint = new IPEndPoint(ipAddress, int.Parse(txtPort.Text));
//2、创建负责监听的socket
Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
socket.Bind(ipEndPoint);
socket.Listen(10);//不要忘了
//3、在线程池中为负责监听的socket启用一个线程
ThreadPool.QueueUserWorkItem(new WaitCallback(ListenClient), socket);
txtHistory.Text += "服务端开始监听客户端连接了...\r\n";
}
//监听客户端连接
public void ListenClient(object obj)
{
Socket socket = (Socket)obj;
while (true)
{
//4、接受客户端的一个连接,创建负责通信的socket
Socket proxSocket = socket.Accept();
clientSocketList.Add(proxSocket);//将通信socket添加到通信socket集合中
//拿到客户端的端口和IP
//txtHistory.Text += proxSocket.RemoteEndPoint.ToString() + "\r\n";
this.Invoke(SetTextDel, proxSocket.RemoteEndPoint.ToString());
//5、在线程池中为通信socket启用一个线程
ThreadPool.QueueUserWorkItem(new WaitCallback(ConnectToClient), proxSocket);
}
}
//与客户端通信
public void ConnectToClient(object obj)
{
Socket socket = (Socket)obj;
try
{
while (socket.Connected)
{
byte[] buffer = new byte[1024 * 1024 * 1];
//6、用通信socket接收客户端发来的信息
int realLength = socket.Receive(buffer, 0, buffer.Length, SocketFlags.None);
string strResult = Encoding.Default.GetString(buffer, 0, realLength);
//客户端调用shutdown
if (realLength<=0)
{
break;
}
//txtHistory.Text += socket.RemoteEndPoint.ToString() + ":" + strResult + "\r\n";
this.Invoke(SetTextDel, socket.RemoteEndPoint.ToString() + ":" + strResult);
}
}
catch (Exception ex)
{
socket.Close();
clientSocketList.Remove(socket); //从通信socket集合中移除当前socket
this.Invoke(SetTextDel, "\r\n客户端退出...");
}
}
public void SetTextForTxtHistory(string strTxt)
{
txtHistory.Text += strTxt + "\r\n";
}
//7、向客户端发送消息
private void btnSend_Click(object sender, EventArgs e)
{
string strTxt = txtMsg.Text;
byte[] data = Encoding.Default.GetBytes(strTxt);
foreach (var socket in clientSocketList)
{
socket.Send(data, 0, data.Length, SocketFlags.None);
}
}
}
}
客户端代码:
namespace ChatClient
{
public delegate void TxtDel(string txt);
public partial class ClientFrm : Form
{
public Socket CurrentSocket { get; set; }
private TxtDel SetTextDel;
public ClientFrm()
{
InitializeComponent();
this.SetTextDel = SetTextForTxtHistory;
}
private void btnCon_Click(object sender, EventArgs e)
{
string ip = txtIP.Text;
IPAddress ipAddress = IPAddress.Parse(ip);
IPEndPoint endPoint = new IPEndPoint(ipAddress, int.Parse(txtPort.Text));
try
{
CurrentSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
CurrentSocket.Connect(endPoint);//服务端没有开启就会出现异常
ThreadPool.QueueUserWorkItem(new WaitCallback(ConnectToService), CurrentSocket);
txtHistory.Text += "与服务器建立连接...\r\n";
}
catch (Exception ex)
{
if (CurrentSocket != null)
{
CurrentSocket.Dispose();
}
}
}
private void btnSend_Click(object sender, EventArgs e)
{
byte[] buffer = Encoding.Default.GetBytes(txtMsg.Text);
CurrentSocket.Send(buffer);
}
public void ConnectToService(object obj)
{
Socket socket = (Socket)obj;
try
{
while (socket != null && socket.Connected)
{
byte[] buffer = new byte[1024 * 1024 * 1];
int realLength = socket.Receive(buffer, 0, buffer.Length, SocketFlags.None);
string strResult = Encoding.Default.GetString(buffer, 0, realLength);
this.Invoke(SetTextDel, socket.RemoteEndPoint.ToString() + ":" + strResult);
}
}
catch (Exception ex)
{
CurrentSocket.Close();
this.Invoke(SetTextDel,"远程主机停止服务...");
}
}
public void SetTextForTxtHistory(string strTxt)
{
txtHistory.Text += strTxt + "\r\n";
}
}
}