1、套接字 socket
socket用于进程间的互相通信,是一种通信机制, 用来描述IP地址和端口信息的。
类型 :
流式 socket 面向连接式的 针对面向连接的TCP服务应用,安全,但是效率较低
报文 socket 面向非连接的,针对无连接的UDP服务应用,效率高,但是安全性能比较低。
2、通信过程
服务端的套接字:
至少两个:一个用于接收客户端的连接请求,不负责与客户端通信,当成功接收一个连接请求后边产生一个对应的套接
字,负责与客户端套接字通信。
客户端:只有一个套接字,负责连接服务端的指定端口并与服务端返回的一个通信套接字通信。
第一步 服务端创建一个监听套接字,并绑定一个节点对象,用于接收客户端的连接请求
第二步 客户端创建一个套接字,并向服务端指定的端口发送连接请求
第三步 服务端接收到连接请求,并产生一个额外的通信套接字来与客户端进行通信,监听套接字就不在于客户端通信了,
他继续监听其他客户端的连接请求
第四步,客户端通过服务端发来的通信套接字与服务端进行通信。
3、套接字例子 客户端与服务器互相发送消息功能
服务端 代码及解释如下
public partial class Form1 : Form
{
public Form1 ( )
{
InitializeComponent ( );
TextBox.CheckForIllegalCrossThreadCalls = false;//取消控件在跨线程调用的检查
}
Thread threadwatch = null; //创建一个监听线程,用来循环监听客户端的连接请求
Socket watchsocket = null;//创建一个监听套接字,用来循环监听客户端的连接请求
// Socket connectsocket = null;
Dictionary<string, Socket> dict = new Dictionary<string, Socket> ( );//创建一个字典,用来存储当前连接到服务端的客户端信息,键是客户端的IP与端口,值就是对应的socket对象
private void button1_Click ( object sender, EventArgs e ) //启动服务端
{
watchsocket = new Socket ( AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp );//实例化监听套接字,AddressFamily.InterNetwork 指定了地址类型 SocketType.Stream,指定了套接字类型 ProtocolType.Tcp指定了协议类型
IPAddress address = IPAddress.Parse ( txtip.Text.Trim ( ) );//创建一个地址对象,包含服务端IP地址信息
IPEndPoint point = new IPEndPoint ( address, int.Parse(txtport.Text.Trim ( )) );//创建一个节点对象,包含了服务器端的IP地址和端口信息
watchsocket.Bind (point); //将监听套接字绑定到节点对象
watchsocket.Listen ( 10 ); //设置服务端的监听队列,参数表示队列的最大长度
threadwatch = new Thread ( WatchConnect ); //实例化监听线程,用来循环监听客户端的连接请求,用多线程来执行是为了防止程序在此中断,保证服务端程序可以执行其他任务
threadwatch.IsBackground = true; //设置监听线程为后台线程,这样在程序退出后该线程会默认结束
threadwatch.Start ( ); //启动监听线程,开始监听客户端连接请求
showMsg ( "服务端启动成功" );//显示消息
}
/// <summary>
/// 监听线程调用的方法,
/// </summary>
void WatchConnect ( )
{
while ( true ) //无线循环保证了监听线程可以不断的监听连接请求,不会因为一个客户端连接请求被接受后而中断监听其他客户端的连接请求
{
Socket connectsocket = watchsocket.Accept ( ); //当接收一个客户端连接请求后,建立连接并返回一个通信套接字与客户端通信
dict.Add(connectsocket.RemoteEndPoint.ToString(),connectsocket);//将该通信套接字存入到我们的字典中,以便于发送消息的时候可以选择客户端
lbonline.Items.Add ( connectsocket.RemoteEndPoint.ToString ( ));//将客户端信息显示在列表中,供服务端发送消息是选择客户端
showMsg ( "客户端连接成功" );
ParameterizedThreadStart pt1 = new ParameterizedThreadStart ( recmessage );//新建一个带参数的委托,用来接收客户端发来的信息,
Thread t1 = new Thread ( pt1 );//使用以上带参数委托新建一个线程,用来监听客户端发来的消息
t1.Start ( connectsocket ); //启动该线程,并将服务端返回给当前客户端连接请求的通信套接字作为参数,以便服务端能区别是谁发来的消息
}
}
/// <summary>
/// 服务端用来接收客户端发来的消息的方法,参数为object对象
/// </summary>
/// <param name="connectsocket"></param>
void recmessage (object connectsocket )
{
while ( true ) //循环接收客户端发来的消息
{
Socket connect = ( Socket ) connectsocket;//将方法的oject对象强制转换成我们的通信套接字对象
byte[] arrmsg = new byte[1024 * 1024 * 2]; //新建一个字节数组,用来存储客户端发来的消息
int length = connect.Receive ( arrmsg );//接收客户端发来的消息
string msgrec = System.Text.Encoding.UTF8.GetString ( arrmsg, 0, length );//将客户端发来的消息解析成字符串
showMsg ( connect.RemoteEndPoint.ToString ( ) + "发送过来消息:" + msgrec );//显示信息
}}
void showMsg (string msg )
{
txtmsg.AppendText ( msg+"\r\n");
}
private void btnsend_Click ( object sender, EventArgs e ) //服务器发送消息给客户端
{
string msg = txtmsgsend.Text.Trim ( ); //获取要发送的信息
byte[] msgbyte = System.Text.Encoding.UTF8.GetBytes ( msg );//将字符串转换成字节数组
//connectsocket.Send ( msgbyte );
string strclient = lbonline.Text;//获取服务端选择的客户端 信息dict[strclient].Send ( msgbyte );//通过字典查找到客户端对应的通信套接字,发送信息
showMsg ( "发送了数据:"+msg);
}
}
客户端代码
public partial class Form1 : Form
{
Thread threadrec = null; //新建一个接受服务端发来消息的线程
Socket socketclient;//新建一个客户端套接字,用来向服务器发送连接请求与接受消息
public Form1 ( )
{
InitializeComponent ( );
TextBox.CheckForIllegalCrossThreadCalls = false;//关闭framework对于控件的跨线程调用检查
}
private void btncon_Click ( object sender, EventArgs e ) //向服务端发送连接请求
{
IPAddress address = IPAddress.Parse ( txtip.Text.Trim());//创建一个地址对象,指明需要连接的服务端的IP地址
IPEndPoint point = new IPEndPoint ( address, int.Parse ( txtport.Text.Trim ( ) ) );//创建一个节点对象,指定需要连接的服务端的IP地址和端口
socketclient = new Socket ( AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp );//实例化套接字,指明地址类型,套接字类型和协议类型
socketclient.Connect(point);//发送连接请求
threadrec = new Thread ( receivemsg );//实例化线程,用来接收服务端发来的消息
threadrec.IsBackground = true;//设置为后台线程
threadrec.Start ( );//启动线程,开始监听
}/// <summary>
/// 接收服务端发来的消息
/// </summary>
void receivemsg ( )
{
while ( true )
{
byte[] arrmsg = new byte[1024 * 1024 * 2];
int length = socketclient.Receive ( arrmsg );
string msgrec = System.Text.Encoding.UTF8.GetString ( arrmsg,0,length );
showMsg ( msgrec );
}
}
void showMsg ( string msg )
{
txtmsg.AppendText ( msg + "\r\n" );
}
/// <summary>
/// 向服务端发送消息
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void btnsend_Click ( object sender, EventArgs e )
{
string strsend = txtsend.Text.Trim ( ); //取得要发送的消息字符串
byte[] sendbyte = System.Text.Encoding.UTF8.GetBytes ( strsend);//将字符串转换为字节数组
socketclient.Send ( sendbyte );//发送消息
}
} Windows Phone 7手机开发、 .Net培训、期待与您交流!