C#Socket网络编程

一、简介

  人与人之间远程交流通信,需要用到电话这个工具,而电脑与电脑之间通讯,也得需要一个类似电话一样的工具来接通。

Socket·所做的就是实现电脑之间的通讯,它是一组接口,拥有相同接口的电脑可以相互传递信息。Socket是应用层与TCP/IP协议族通信的中间软件抽象层。在设计模式中,Socket其实就是一个门面模式,它把复杂的TCP/IP协议族隐藏在Socket接口后面,对用户来说,一组简单的接口就是全部,让Socket去组织数据,以符合指定的协议

 

 

 

 

 

二、工作原理

先来看一张图:

 

1、服务器端先初始化Socket,然后与端口绑定(bind),对端口进行监听(listen),调用accept阻塞,等待客户端连接。

//选择ip地址版本,套接字类型,协议类型,若是TCP则SocketType为Stream
Socket socketwatch = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); //创建IP地址跟端口对象 IPAddress ip = IPAddress.Any;
//用ip跟端口号初始化得到IPEndPoint类型的实例 IPEndPoint point
= new IPEndPoint(ip, Convert.ToInt32(txtPort.Text)); socketwatch.Bind(point); ShowMsg("监听成功"); //监听队列 socketwatch.Listen(10);
//开辟新线程一直监听客户端的连接
Thread th = new Thread(Listens);
//转为后台线程
th.IsBackground = true;
//传入的socketwatch为Listen的参数
th.Start(socketwatch);

void Listens(object o) // 参数一定得是object 类型
{
Socket socketwatch = o as Socket;
while (true)
{
try
{
//等待客户端的连接,并创建一个用于通信的socket
Socket socketSend = socketwatch.Accept(); //如果把Accept()放在主线程里会一直等待卡死界面
ShowMsg(socketSend.RemoteEndPoint.ToString() + “: 连接成功”);

//byte[] buffer = new byte[1024 * 1024];
//int x = socketsend.Receive(buffer);
//string str = Encoding.UTF8.GetString(buffer, 0, x);

//开辟新的后台线程一直接收客户端发来的消息
Thread th1 = new Thread(Recive);
th1.IsBackground = true;
th1.Start(socketSend);
}
catch
{}

}

 

 

 

2、在这时如果有个客户端初始化一个Socket,然后连接服务器(connect),如果连接成功,这时客户端与服务器端的连接就建立了。

Socket socketSend = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                IPAddress iP = IPAddress.Parse(textBox1.Text);
                IPEndPoint point = new IPEndPoint(iP, Convert.ToInt32(textBox2.Text));
                socketSend.Connect(point);
                ShowMsg("连接成功");

 

3、客户端发送数据请求,服务器端接收请求并处理请求,然后把回应数据发送给客户端,客户端读取数据,最后关闭连接,一次交互结束。

//客户端发送数据
  string str = textBox4.Text.Trim();
            byte[] buffer = System.Text.Encoding.UTF8.GetBytes(str);
            socketSend.Send(buffer);
            textBox4.Text = "";
//服务端接收数据
void Recive(object o)
        {
            Socket socketSend = o as Socket;
            while (true)
            {
                try
                {

                    byte[] buffer = new byte[1024 * 1024];
                    //把输入文本传给服务端,x表示实际长度
                    int x = socketSend.Receive(buffer);
            //当没有数据传输时,x长度为0,直接退出,否则会一直打印空值  
if (x == 0) { break; } string str = Encoding.UTF8.GetString(buffer, 0, x); ShowMsg(socketSend.RemoteEndPoint + ":" + str); } catch { } } }
//服务端发送数据

string str = txtMsg.Text.Trim();
byte[] buffer = System.Text.Encoding.UTF8.GetBytes(str);
socketSend.Send(buffer);
txtMsg.Text = “”;

 

//客户端接收数据,因为

void Receives()
{

while (true)
{
try
{

byte[] buffer = new byte[1024 * 1024];
//把输入文本传给服务端,x表示实际长度
int e = socketSend.Receive(buffer);
if (e == 0)
{
break;
}
string str = Encoding.UTF8.GetString(buffer, 0, e);
ShowMsg(socketSend.RemoteEndPoint + “:” + str);
}
catch
{}}

 

三、Socket常用的方法

 

1、绑定:socket.BInd(IPAndPiont),服务端绑定端口号,

2、监听:socket.Listen(int x),x表示监听端口数

3、阻塞:socket.Accept(),当有客户发起连接请求时,取消线程阻塞,所以一般不会在主线程里调用Accept

4、连接:socket.Connect(),客户端在服务端准备就绪之后,发送连接请求

5、socket.Close(),关闭连接

 

四、注意事项

1、在winform里面创建线程有时候会被系统拦截,所以只要在winform中新建了子线程都可以在程序里加入:

 //只要碰到线程问题,先把这句话加进去
Control.CheckForIllegalCrossThreadCalls = false;

2、Accpet方法一定不要用在主线程里面,会阻塞主界面