进程通信机制。用来描述IP地址和端口,是一个通信链的句柄。
两种类型:
流式:一种面向连接的socket,针对面向连接的tcp服务应用,安全,但效率低。
数据报式:一种无连接的socket,对应于无连接的udp服务应用。不安全(丢失),顺序混乱,在接收端要分析重排及要求重发,但效率高。
服务端与客户端通讯过程
服务端
申请一个socket--绑定到一个ip地址和端口--开启监听,等待接收和连接
客户端
申请一个socket--连接服务器(指明ip地址和端口号)
服务端接到连接请求后产生一个新的socket与客户端建立连接并进行通讯。原监听socket继续监听。
注意:
至少要定义一个要连接的远程主机的ip和端口号。
端口号必须在1到65535之间,最好在1024以后。
要连接的远程主机必须正在监听指定端口。
一个socket一次只能连接一台主机。
socket关闭后无法再次使用。
每个socket对象只能一台远程主机连接。如果想连接到多台远程主机,必须创建多个socket对象。
//简单服务器与客户端通信实现
//服务端
//在构造函数里初始化完组件后取消下跨线程检查。
Control.CheckForIllegalCrossThreadCalls=false;
//定义一个全局的socket
Socket sockServer;
//创建一个字典集合保存与客户端通信的套接字 界面上放置一个listview显示当前连接的客户端ip终结点 listViewOnline
Dictionary<string,Socket> dictSocket=new Dictionary<string,Socket>();
socketServer=new Socket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.TCP);
IPAddress address=IPAddress.Parse(127.0.0.1);
IPEndPoint endPoint=new IPEndPoint(address,Convert.ToInt32(8001));
//监听套接字绑定到端口上
socketServer.Bind(endPoint);
//设置监听队列的最大长度
socketServer.Listen(10);
//服务已启动。。。
//可以开启一个线程监听并接收客户端连接请求
Thread threadWatch=new Thread(WatchConnet);
threadWatch.IsBackground=true;
threadWatch.Name="watchThread";
threadWatch.Start();
//WatchConnect监听连接请求
bool isWatch=true;
void WatchConnect()
{
try
{
while(isWatch)
{
//监听并接收客户端连接请求,如果有连接过来则返回一个负责通信的套接字
Socket sokMsg=sockServer.Accept();
//获取客户端终结点
string clientKey=sokMsg.RemoteEndPoint.ToString();
//添加到listview中
listViewOnline.Items.Add(clientKey,clientKey,"");
//添加到集合中
dictSocket.Add(clientKey,sokMsg);
//有客户端连接
//可以创建一个通信线程
Thread threadRecMsg=new Thread(WatchMsg);
threadRecMsg.IsBackground=true;
threadRecMsg.Name="threadRecMsg";
threadRecMsg.Start(sokMsg);
}
}
catch(Exception ex){}
}
//接收客户端发来的消息
void WatchMsg(object sok)
{
Socket sokMsg=null;
try
{
while(isWatch)
{
sokMsg= sok as Socket;
byte[] arrMsg=new byte[1024*1024];
int length=sokMsg.Receive(arrMsg);
string msg=Encoding.UTF8.GetString(arrMsg,0,arrMsg.Length);
//客户端发送的内容:msg
}
}
catch(Exception ex){}
}
//向指定客户端发送消息
if(listViewOnline.SelectedItems.Count>0)
{
string clientKey=listViewOnline.SelectedItems[0].Text;
//判断通信套接字是否包含此客户端的网络节点
if(dictSocket.ContainsKey(clientKey))
{
string strMsg="发送给客户端"+clientKey+"的消息";
byte[] arrMsg=Encoding.UTF8.GetBytes(strMsg);
//根据节点找到字典中对应的通信套接字对象,并调用send方法向客户端发送消息。
dictSocket[clientKey].Send(arrMsg);
}
}
//客户端
//创建一个全局socket
Socket sokClient;
sokClient=new Socket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp);
IPEndPoint endpoint=new IPEndPoint(IPAddress.Parse(127.0.0.1),int.Parse(8001));
try
{
sokClient.Connect(endpoint);
//可以创建一个线程与服务端通信
Thread threadClient=new Thread(WatchMsgFromServer);
threadClient.IsBackground=true;
threadClient.Name="WatchMsgFromServer";
threadClient.Start();
}
catch(Exception ex){}
//监听通信
void WatchMsgFromServer()
{
try
{
while(true)
{
byte[] arrMsg=new byte[1024*1024];
int realLength=sokClient.Receive(arrMsg);
string strMsg=Encoding.UTF8.GetString(arrMsg,0,realLength);
//服务器发送的内容:strMsg
}
}
catch(Exception ex){}
}
//给服务端发送消息
string msgSend=“给服务端发送的消息”;
byte[] arrMsg=Encoding.UTF8.GetBytes(msgSend);
sokClient.Send(arrMsg);