TCP/IP协议学习(五) 基于C# Socket的C/S模型

摘要:
C#通过提供的SocketAPI实现了对TCP/IP协议栈的封装,让实现C/S模型变得更加简单,对于入门TCP/IP协议学习十分有帮助。Socket通讯实现参考标准的流程如图所示,·服务器工作:1.创建Socket套接字,绑定指定host,并监听。了解了上述Socket通讯的主要过程,在结合C#网络编程的特性,就可以实现如下C/S服务器。

TCP/IP协议作为现代网络通讯的基石,内容包罗万象,直接去理解理论是比较困难的;然而通过实践先理解网络通讯的理解,在反过来理解学习TCP/IP协议栈就相对简单很多。C#通过提供的Socket API实现了对TCP/IP协议栈的封装,让实现C/S模型变得更加简单,对于入门TCP/IP协议学习十分有帮助。

Socket通讯实现参考标准的流程如图所示,

TCP/IP协议学习(五) 基于C# Socket的C/S模型第1张·

服务器工作:

1.创建Socket套接字,绑定指定host,并监听。

2.线程堵塞等待用户端请求,当客户端请求到达时建立连接。

3.连接建立完成后,读取请求并处理,然后将处理结果返回给客户端。

4. 服务器等待客户端关闭连接,连接关闭后,一次Socket通讯结束。

客户端工作:

1.创建Socket套接字, 建立连接,发送连接请求数据

2. 请求成功后,等待服务器返回响应

3.服务器回应成功后,处理数据,直到主动关闭连接。

了解了上述Socket通讯的主要过程,在结合C#网络编程的特性,就可以实现如下C/S服务器。客户端的实现比较简单,主要分四个步骤:

1.建立tcp连接(等同于socket 和 connect),处理连接失败状态

2.对于建立成功的连接,发送数据,并等待服务器返回

3.接收数据,输出到编辑框

4.关闭连接

private void button1_Click(objectsender, EventArgs e)
{
    try
    {
        string s_ipaddress0 =textBox1.Text;
        string s_ipaddress1 =textBox2.Text;
        string s_ipaddress2 =textBox3.Text;
        string s_ipaddress3 =textBox4.Text;
        string s_port =textBox5.Text;
        //限定port的合法性
        boolisPort;
        intport;
        isPort = Int32.TryParse(s_port, outport);
        if (!(isPort && port >= 0 && port <= 65536))
        {
            OutToClient("Port is Invalid!");
            return;
        }
        //限定ip地址的合法性
        string host = s_ipaddress0 + "." + s_ipaddress1 + "." + s_ipaddress2 + "." +s_ipaddress3;
        if (!IsIpAdress(host))
        {
            OutToClient("IpAdress is invaild!");
            return;
        }
        IPAddress ip =IPAddress.Parse(host);
        IPEndPoint ipe = new IPEndPoint(ip, port); //Ip端口绑定 如192.168.1.48:80
        //发送框不能为空, 不然会导致GetBytes出错
        if (textBox6.Text == "")
        {
            OutToClient("Send Text is empty!");
            return;
        }
        OutToClient("Conneting...");
        int timeout = 1000;
        //tcpClient连接到指定端口,并处理超时
        TcpClient NetworkClient =TimeOutSocket.Connect(ipe, timeout);
        NetworkStream ntwStream =NetworkClient.GetStream();
        if (!ntwStream.CanWrite)
        {
            OutToClient("Data can not be write!");
            return;
        }
        //向绑定地址端口发送数据
         OutToClient("Client send:" +textBox6.Text);
        string sendStr =textBox6.Text;
        byte[] by_send =Encoding.ASCII.GetBytes(sendStr);
        ntwStream.Write(by_send, 0, by_send.Length);
        //等待服务器端返回数据
        string recvStr = "";
        byte[] recvBytes = new byte[4096];
        int bytes = ntwStream.Read(recvBytes, 0, recvBytes.Length);
        //将接收到数据转发输出到Client编辑框
        recvStr += Encoding.ASCII.GetString(recvBytes, 0, bytes);
        OutToClient(recvStr);
        //关闭连接, 一次发送完成
ntwStream.Close();                                              
        NetworkClient.Close();
        OutToClient("Conneting Close!
");
    }
    catch(ArgumentNullException ii)
    {
        OutToClient("ArgumentNullException: "+ii);
    }
    catch(SocketException ii)
    {
        OutToClient("Socket failed! ");
    }
    catch(Exception ii)
    {
        OutToClient("Conneting faild!" +ii);
    }
}

服务器内的代码涉及到的知识多一些

1.通过按键1开辟监听线程,用于接收

2.监听线程创建Socket套接字,绑定到指定端口并监听

3.监听线程堵塞在等带连接建立

4.连接建立后监听线程读取客户端数据并回送给客户端处理后数据,然后循环堵塞在连接建立

5.通过按键2删除Socket套接字触发异常,结束线程

按照上述的流程,程序如下:

//新建线程 开始监听
private void button1_Click(objectsender, EventArgs e)
{
    try
    {
        isConnectExit = false;
        button1.Enabled = false;
        button2.Enabled = true;
        Thread Listen_thread = newThread(ListenClientConnect);
        Listen_thread.IsBackground = true;
        Listen_thread.Start();
    }
    catch(Exception ii)
    {
        OutToServer("Connet faild!" +ii);
    }
}
//监听线程 主要处理数据接收发送
private void ListenClientConnect(objectobj)
{
    string s_ipaddress0 =textBox1.Text;
    string s_ipaddress1 =textBox2.Text;
    string s_ipaddress2 =textBox3.Text;
    string s_ipaddress3 =textBox4.Text;
    string s_port =textBox5.Text;
    //限定port的合法性
    boolisPort;
    intport;
    isPort = Int32.TryParse(s_port, outport);
    if (!(isPort && port >= 0 && port <= 65536))
    {
        OutToServer("Port is Invalid!");
        return;
    }
    //限定ip地址的合法性
    string host = s_ipaddress0 + "." + s_ipaddress1 + "." + s_ipaddress2 + "." +s_ipaddress3;
    if (!IsIpAdress(host))
    {
        OutToServer("IpAdress is invaild!");
        return;
    }
    IPAddress ip =IPAddress.Parse(host);
    IPEndPoint ipe = newIPEndPoint(ip, port);
    //新建socket通讯 绑定指定IP+Port 并监听
    server_socket = newSocket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
    server_socket.Bind(ipe);
    server_socket.Listen(10);
    OutToServer("wait for connect...");
    while (isConnectExit == false)
    {
        Socket CurrentSocket;
        try
        {
            //等待连接 完成三次握手
            CurrentSocket =server_socket.Accept();
            if(isConnectExit == true)
            {
                CurrentSocket.Close();                     //关闭Socket
server_socket.Close();
                break;
            }
            OutToServer("Get a Connect!");
            ServerProcess(CurrentSocket);
        }
        catch
        {
            OutToServer("Connet exti!");
        }
    }
}
//断开连接
private void button2_Click(objectsender, EventArgs e)
{
    isConnectExit = true;
    button2.Enabled = false;
    button1.Enabled = true;
    if (server_socket != null)
    {
        server_socket.Close();
    }
}

如此就完成了简单的C/S服务器功能。

实际测试界面如下:

TCP/IP协议学习(五) 基于C# Socket的C/S模型第2张

TCP/IP协议学习(五) 基于C# Socket的C/S模型第3张

具体源码参考:C/S架构客户端-服务器下载

备注:本程序仅用于演示TCP socket通信流程,服务器端能够监听的IP地址只有本机IP或者127.x.x.1(环回地址), 端口不能为80(和本机http端口冲突)。

免责声明:文章转载自《TCP/IP协议学习(五) 基于C# Socket的C/S模型》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇1045-access denied for user 'root'@c# 正则表达式 匹配回车下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

金蝶云星空使用WebAPI来新增单据

有很多客户需求在后台自动生成某张单据,金蝶云星空提供了WebApi,包含了保存,提交,审核,删除单据的接口,下面以生产订单的保存,提交,审核为例,说明一下应用WebApi后台自动生成生产订单的功能,下面是代码示例,其他单据可以根据示例代码做相应的修改: using Kingdee.BOS.Core.Bill.PlugIn;using System;usin...

Quartz+Spring 实现定时任务的 管理和监控

 0,监控的意义 (1)能够查看有多少定时任务,用的什么执行策略,便于管理 (2)能够通过界面操作停止或启动某个定时任务,便于管理 (3)能够通过界面操作改变某个定时任务的执行策略,便于管理 1,pom.xml 文件添加jar 1 <!-- quartz监控 --> 2 <dependency> 3 <gro...

在javaweb的项目当中实现随机数字的生成

首先,需要在javaweb的项目当中新建一个Servlet文件,然后再web.xml中配置一下: 这样运行的时候就可以通过“http://localhost:8080/Response/Response02”的地址访问到我们的Servlet。 开始代码的编写吧: 首先,我们需要写一个生成随即数字的方法,我们这次实现随即生成七位数的数字: priv...

java执行linux shell命令,并拿到返回值

1 packagecom.pasier.xxx.util; 2 3 importjava.io.IOException; 4 importjava.io.InputStream; 5 importjava.nio.charset.Charset; 6 7 importorg.slf4j.Logger; 8 importorg.slf4j.LoggerF...

statement 、prepareStatement的用法和解释

转自:http://blog.csdn.net/QH_JAVA/article/details/48245945 一、prepareStatement 的用法和解释 1.PreparedStatement是预编译的,对于批量处理可以大大提高效率. 也叫JDBC存储过程 2.使用 Statement 对象。在对数据库只执行一次性存取的时侯,用 Stateme...

json : json数据解析(一)

在项目中经常用到json格式的数据转换与解析,先前写过一些小例子,现在整理下,以备后用和帮助后来者。 言归正传: 使用到的jar包 :json-lib-2.4-jdk15.jar,当然你也可以用自己版本的,一般都没啥问题。 一、用于测试数据的类: 1.Student 1 /* 2 * To change this template, choos...