- socket 类提供一系列的方法实现同步或异步的通信
- socket 类提供了异步方法,比如:同步方法中 Receive对应BeginReceive/EndReceive 方法。
同步模式
如果是单线程的程序,可以采用同步操作模式。如果采用面向连接的TCP协议,
server 端可以调用Bind方法指定监听的端口,再调用Listen方法启动监听,Accept方法处理连接请求并返回一个socket,可以用这个socket与client端交换数据。
client 端直接调用Connect方法以连接到server,可以调用Send/Receive 来与server端交换数据。
2 异步
如果采用面向连接的TCP协议,server 端调用BeginAccept与EndAccept处理连接请求。
client 端调用BeginConnect 与EndConnect 连接到监听主机,调用BeginSend与EndSend,BeginReceive与EndReceive 同server 交换数据
-
如果采用异步模式,在同一socket进行多次发送/接收数据并不是严格按照它的调用顺序来执行的。
-
当socket 通信完成后。调用Shutdown方法,停止发送或接收数据,再调用Close释放与socket相关的资源。
下面代码示例,演示两个client 连接到同一个server,通过server转发数据,实现两个client端通信
server 端代码
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Net;
using System.Net.Sockets;
using System.Collections;
using System.Threading;
namespace socketServer01
{
class Program
{
//用于保存连接的所有的client
public static Hashtable nickName;
public static Hashtable nickNameByConnect;
static void Main(string[] args)
{
nickName = new Hashtable(100);
nickNameByConnect = new Hashtable(100);
//初始化
IPAddress ip = IPAddress.Parse("0.0.0.0");
TcpListener listener = new TcpListener(ip, 50000);
//直接初始化端口create listener
//TcpListener listener = new TcpListener(50000);
listener.Start();
Console.WriteLine("Listener 已启动");
while (true)
{
//接收连接请求
if (listener.Pending())
{
TcpClient client = listener.AcceptTcpClient();
Console.WriteLine("{0} ,you are connected", client.Client.RemoteEndPoint.ToString());
DoCommunicate chatClient = new DoCommunicate(client);
}
}
}
}
class DoCommunicate
{
System.Net.Sockets.TcpClient client;
System.Net.Sockets.NetworkStream reader;
// System.IO.StreamReader reader;
System.IO.StreamWriter writer;
string nickName;
public DoCommunicate(System.Net.Sockets.TcpClient tcpClient)
{
//create our TcpClient
client = tcpClient;
//create a new thread
Thread chatThread = new Thread(new ThreadStart(startChat));
//start the new thread
chatThread.Start();
}
/// <summary>
/// 接收消息
/// </summary>
private void runChat()
//use a try...catch to catch any exceptions
{
try
{
//set out line variable to an empty string
string line = "";
while (true)
{
//read the curent line
byte[] bytes = new byte[1024];
//接收消息
reader.Read(bytes, 0, bytes.Length);
line =Encoding.UTF8.GetString(bytes,0,bytes.Length);
Console.WriteLine("收到:" + line);
//send our message
//发生消息给所有在线的client
SendMsgToAll(nickName, line);
}
}
catch (Exception e44)
{
Console.WriteLine(e44);
}
}
/// <summary>
/// 发送数据,并启动接收线程
/// </summary>
private void startChat()
{
create our StreamReader object to read the current stream
reader = client.GetStream();
byte[] bytes= Encoding.UTF8.GetBytes("Welcome to PCChat! \r\n");
client.GetStream().Write(bytes,0,bytes.Length);
nickName = client.Client.RemoteEndPoint.ToString();
//add their nickname to the chat server
Program.nickName.Add(nickName, client);
Program.nickNameByConnect.Add(client, nickName);
//send a system message letting the other user
//know that a new user has joined the chat
///向所有在线的client、发送通知
SendSystemMessage("** " + nickName + " ** Has joined the room");
byte[] data=Encoding.UTF8.GetBytes("Now Talking.....\r\n");
client.GetStream().Write(data, 0, data.Length);
client.GetStream().Flush();
//ensure the buffer is empty
// writer.Flush();
//create a new thread for this user
// 开启为这个client开启一个线程 用于接收它发送的消息
Thread chatThread = new Thread(new ThreadStart(runChat));
//start the thread
chatThread.Start();
}
static void SendSystemMessage(string msg)
{
//create our StreamWriter object
System.IO.StreamWriter writer;
ArrayList ToRemove = new ArrayList(0);
//create our TcpClient array
if (Program.nickName.Count > 0)
{
System.Net.Sockets.TcpClient[] tcpClients = new System.Net.Sockets.TcpClient[Program.nickName.Count];
//copy the nickname value to the chat servers list
Program.nickName.Values.CopyTo(tcpClients, 0);
//loop through and write any messages to the window
for (int i = 0; i < tcpClients.Length; i++)
{
try
{
if (msg.Trim() == "" || tcpClients[i] == null)
continue;
//writer =new System.IO.StreamWriter(tcpClients[i].GetStream());
//writer.WriteLine(msg);
//writer.Flush();
//writer = null;
byte[] bytes = Encoding.UTF8.GetBytes(msg);
tcpClients[i].GetStream().Write(bytes,0,bytes.Length);
tcpClients[i].GetStream().Flush();
}
catch (Exception e)
{
Program.nickName.Remove(tcpClients[i]);
Program.nickNameByConnect.Remove(tcpClients[i]);
}
}
}
}
static void SendMsgToAll(string nick, string msg)
{
//create a StreamWriter Object
System.IO.StreamWriter writer;
ArrayList ToRemove = new ArrayList(0);
//create a new TCPClient Array
System.Net.Sockets.TcpClient[] tcpclients = new System.Net.Sockets.TcpClient[Program.nickName.Count];
//copy the users nickname to the CHatServer values
Program.nickName.Values.CopyTo(tcpclients, 0);
for (int i = 0; i < tcpclients.Length; i++)
{
try
{
if (msg.Trim() == "" || tcpclients[i] == null)
continue;
writer = new System.IO.StreamWriter(tcpclients[i].GetStream());
writer.WriteLine(nick + ":" + msg);
writer.Flush();
writer = null;
}
catch (Exception e)
{
string str = (string)Program.nickNameByConnect[tcpclients[i]];
SendSystemMessage("**" + str + "***has left the room"+"\r\n");
Program.nickName.Remove(str);
Program.nickNameByConnect.Remove(tcpclients[i]);
}
}
}
}
}
client端代码
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Net;
using System.Net.Sockets;
namespace socketClient02
{
public partial class Form1 : Form
{
public static TcpClient tcpClient;
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
try
{
tcpClient= new TcpClient();
tcpClient.Connect("192.168.1.158", 50000);
txtReceive.AppendText("连接成功\r\n");
//开启线程用于接收远端发过来的信息
System.Threading.Thread ReceThread = new System.Threading.Thread(new System.Threading.ThreadStart(run));
ReceThread.Start();
}
catch (Exception ex)
{
this.txtReceive.Text = ex.Message;
}
}
private void textBox1_TextChanged(object sender, EventArgs e)
{
}
private void run()
{
if (tcpClient != null)
{
try
{
//create our StreamReader Object, based on the current NetworkStream
System.Net.Sockets.NetworkStream stream = tcpClient.GetStream();
while (true)
{
byte[] bytes = new byte[1024];
stream.Read(bytes, 0, bytes.Length);
string msg = Encoding.UTF8.GetString(bytes);
this.txtReceive.AppendText(msg);
this.txtReceive.AppendText("\r\n");
}
}
catch (Exception e)
{
this.txtReceive.AppendText("socket 连接已断开");
tcpClient.Close();
}
}
}
private void btnSend_Click(object sender, EventArgs e)
{
//用于发送消息到远端
string msg = this.textBox3.Text;
if (msg != null)
{
System.Net.Sockets.NetworkStream stream = tcpClient.GetStream();
txtSend.AppendText(DateTime.Now.ToShortTimeString()+" 发送:" + msg + "\r\n");
byte[] bytes = Encoding.UTF8.GetBytes(msg);
stream.Write(bytes, 0, bytes.Length);
this.textBox3.Text = "";
}
}
}
}
源码下载:sourceCode