TCP协议发送和接受文本消息

引用总结:

对于TCP协议我不想说太多东西,这属于大学课程,又涉及计算机科学,而我不是“学院派”,对于这部分内容,我觉得作为开发人员,只需要掌握与程序相关的概念就可以了,不需要做太艰深的研究。


我们首先知道TCP是面向连接的,它的意思是说两个远程主机(或者叫进程,因为实际上远程通信是进程之间的通信,而进程则是运行中的 程序),必须首先进行一个握手过程,确认连接成功,之后才能传输实际的数据。比如说进程A想将字符串“It's a fine day today”发给进程B,它首先要建立连接。在这一过程中,它首先需要知道进程B的位置(主机地址和端口号)。随后发送一个不包含实际数据的请求报文,我 们可以将这个报文称之为“hello”。如果进程B接收到了这个“hello”,就向进程A回复一个“hello”,进程A随后才发送实际的数据 “It's a fine day today”。


关于TCP第二个需要了解的,就是它是全双工的。意思是说如果两个主机上的进程(比如进程A、进程B),一旦建立好连接,那么数据就既可以由A流向B,也可以由B流向A。除此以外,它还是点对点的,意思是说一个TCP连接总是两者之间的,在发送中,通过一个连接将数据发给多个接收方是不可能的。TCP还有一个特性,就是称为可靠的数据传输,意思是连接建立后,数据的发送一定能够到达,并且是有序的,就是说发的时候你发了ABC,那么收的一方收到的也一定是ABC,而不会是BCA或者别的什么。

编程中与TCP相关的最重要的一个概念就是套接字。我们应该知道网络七层协议,如果我们将上面的应用程、表示层、会话层笼统地算作一 层(有的教材便是如此划分的),那么我们编写的网络应用程序就位于应用层,而大家知道TCP是属于传输层的协议,那么我们在应用层如何使用传输层的服务呢 (消息发送或者文件上传下载)?大家知道在应用程序中我们用接口来分离实现,在应用层和传输层之间,则是使用套接字来进行分离。它就像是传输层为应用层开 的一个小口,应用程序通过这个小口向远程发送数据,或者接收远程发来的数据;而这个小口以内,也就是数据进入这个口之后,或者数据从这个口出来之前,我们 是不知道也不需要知道的,我们也不会关心它如何传输,这属于网络其它层次的工作。

--------------------------------------------------------------------------

对于TCP协议发送和接受消息,三种常用的方法:socket、封装了socket的tcplistensr tcpclient、更高级封装的streamreader streamwriter,socket是万能的,最灵活,同时工作量也最大,后面会提到要考虑消息界限的问题。

用高级类来实现TCP通信,client和server都在同一台电脑上

服务器端代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using System.Net.Sockets;
using System.Net;
//using System.Threading;
using System.IO;

namespace ConsoleServer
{
    class Program
    {
        static void Main(string[] args)
        {
            IPEndPoint IpEnd = new IPEndPoint(IPAddress.Any,8500);
            TcpListener ServerListener = new TcpListener(IpEnd);
            ServerListener.Start(); 
            Console.WriteLine("Server is running");
            TcpClient remoteclient = ServerListener.AcceptTcpClient();
            Console.WriteLine("{0}----->{1}", remoteclient.Client.LocalEndPoint, remoteclient.Client.RemoteEndPoint);
            while(true)
            {
                try
                {
                    NetworkStream ns = remoteclient.GetStream();
                    StreamReader SR = new StreamReader(ns);
                    StreamWriter SW = new StreamWriter(ns);
                    //写数据给客户端
                    byte[] dafa = new byte[100];
                    string welcomeA = "welcome to my test server A";
                    string welcomeB = "welcome to my test server B";
                    string welcomeC = "welcome to my test server C";
                    //dafa = ASCIIEncoding.ASCII.GetBytes(welcomeA);
                    //从客户端读取数据
                    int buflen = remoteclient.Available;
                    byte[] buffer = new byte[1024];
                    ns.Read(buffer, 0, buflen);    
                    string remotecommand = System.Text.ASCIIEncoding.ASCII.GetString(buffer).Substring(0, buflen);
                    //stream readline
                    //string remotecommand = SR.ReadLine();
                    Console.WriteLine("receive:"+remotecommand);
                    //Console.ReadLine();
                    switch(remotecommand)
                    {
                        case "A":
                            dafa = ASCIIEncoding.ASCII.GetBytes(welcomeA);
                            //SW.WriteLine(welcomeA);
                            //SW.Flush();
                            break;
                        case"B":
                            dafa = ASCIIEncoding.ASCII.GetBytes(welcomeB);
                            //SW.WriteLine(welcomeB);
                            //SW.Flush();
                            break;
                        case"C":
                            dafa = ASCIIEncoding.ASCII.GetBytes(welcomeC);
                            //SW.WriteLine(welcomeC);
                            //SW.Flush();
                            break;
                    }
                    ns.Write(dafa, 0, dafa.Length);
                  
                }
                catch (Exception ex)
                {
                    Console.WriteLine("connect error"+ex.Message);
                    return;
                }
            }
            /*Q键退出
            Console.WriteLine("\n\nQ键退出");
            ConsoleKey key;
            do{
                key = Console.ReadKey().Key;
            }while(key!=ConsoleKey.Q);
            */
        }     
    }
}


客户端代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

//using System.Net;
using System.IO;
using System.Net.Sockets;
namespace ConsoleClient
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("client is running");
            /*
            try
            {
                for (int i = 1; i < 5; i++)
                {
                    TcpClient client = new TcpClient();
                    client.Connect("localhost", 8500);
                    Console.WriteLine("{0}----->{1}", client.Client.LocalEndPoint, client.Client.RemoteEndPoint);
                    NetworkStream ns = client.GetStream();
                    Byte[] buffer = new Byte[1024];
                    string data = "this is test";
                    buffer = ASCIIEncoding.ASCII.GetBytes(data);
                    ns.Write(buffer,0,data.Length);
                    Console.WriteLine("send:"+data+"\n");
                    
                }
            }
             
            catch(Exception ex)
            {
                Console.WriteLine("connect error"+ex.Message);
                //return;
            }
            */
            TcpClient clienttcp = new TcpClient();
            clienttcp.Connect("localhost", 8500);
            Console.WriteLine("{0}----->{1}", clienttcp.Client.LocalEndPoint, clienttcp.Client.RemoteEndPoint);
            NetworkStream nstcp = clienttcp.GetStream();
            StreamReader SR = new StreamReader(nstcp);
            StreamWriter SW = new StreamWriter(nstcp);
            while (true)
            {
                
                Random rd = new Random();
                byte da = (byte)rd.Next(65, 68);
                byte[] readda = new byte[1024];
                readda[0] = da;
                nstcp.Write(readda,0,1);
                //string str = ASCIIEncoding.ASCII.GetString(readda).Substring(0,1);
                //Console.WriteLine("send:"+str);
                
                //SW.WriteLine(str);
                //SW.Flush();
                //Console.ReadLine();
                //Byte[] buffer = new Byte[1024];
                //string data = "this is test";
                //buffer = ASCIIEncoding.ASCII.GetBytes(data);
                //nstcp.Write(buffer, 0, data.Length);
                //Console.WriteLine("send:"+data);
                
                int datalen = clienttcp.Available;
                byte[]receivedata = new byte[2048];
                nstcp.Read(receivedata,0,datalen);
                //string rcdata = SR.ReadLine();
                string rcdata = ASCIIEncoding.ASCII.GetString(receivedata).Substring(0,datalen);
                Console.WriteLine("receive:"+rcdata);
                
            }
             
            /* Q键退出
            Console.WriteLine("\n\nQ键退出");
            ConsoleKey key;
            do
            {
                key = Console.ReadKey().Key;
            }while(key!=ConsoleKey.Q);
            */
        }
    }
}

在同一台电脑上运行结果,会出现接受到信息为空或者把两次信息当一次来接受的情况

TCP协议发送和接受文本消息_第1张图片


下面用类StreamReader和StreamWriter来实现:


服务器端代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using System.Net.Sockets;
using System.Net;
//using System.Threading;
using System.IO;

namespace ConsoleServer
{
    class Program
    {
        static void Main(string[] args)
        {
            IPEndPoint IpEnd = new IPEndPoint(IPAddress.Any,8500);
            TcpListener ServerListener = new TcpListener(IpEnd);
            ServerListener.Start(); 
            Console.WriteLine("Server is running");
            TcpClient remoteclient = ServerListener.AcceptTcpClient();
            Console.WriteLine("{0}----->{1}", remoteclient.Client.LocalEndPoint, remoteclient.Client.RemoteEndPoint);
            while(true)
            {
                try
                {
                    NetworkStream ns = remoteclient.GetStream();
                    StreamReader SR = new StreamReader(ns);
                    StreamWriter SW = new StreamWriter(ns);
                    //写数据给客户端
                    //byte[] dafa = new byte[100];
                    string welcomeA = "welcome to my test server A";
                    string welcomeB = "welcome to my test server B";
                    string welcomeC = "welcome to my test server C";
                    //dafa = ASCIIEncoding.ASCII.GetBytes(welcomeA);
                    //从客户端读取数据
                    //int buflen = remoteclient.Available;
                    //byte[] buffer = new byte[1024];
                    //ns.Read(buffer, 0, buflen);    
                    //string remotecommand = System.Text.ASCIIEncoding.ASCII.GetString(buffer).Substring(0, buflen);
                    //stream readline
                    string remotecommand = SR.ReadLine();
                    Console.WriteLine("receive:"+remotecommand);
                    //Console.ReadLine();
                    switch(remotecommand)
                    {
                        case "A":
                            //dafa = ASCIIEncoding.ASCII.GetBytes(welcomeA);
                            SW.WriteLine(welcomeA);
                            SW.Flush();
                            break;
                        case"B":
                            //dafa = ASCIIEncoding.ASCII.GetBytes(welcomeB);
                            SW.WriteLine(welcomeB);
                            SW.Flush();
                            break;
                        case"C":
                            //dafa = ASCIIEncoding.ASCII.GetBytes(welcomeC);
                            SW.WriteLine(welcomeC);
                            SW.Flush();
                            break;
                    }
                    //ns.Write(dafa, 0, dafa.Length);
                  
                }
                catch (Exception ex)
                {
                    Console.WriteLine("connect error"+ex.Message);
                    return;
                }
            }
            /*Q键退出
            Console.WriteLine("\n\nQ键退出");
            ConsoleKey key;
            do{
                key = Console.ReadKey().Key;
            }while(key!=ConsoleKey.Q);
            */
        }     
    }
}


客户端代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

//using System.Net;
using System.IO;
using System.Net.Sockets;
namespace ConsoleClient
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("client is running");
            /*
            try
            {
                for (int i = 1; i < 5; i++)
                {
                    TcpClient client = new TcpClient();
                    client.Connect("localhost", 8500);
                    Console.WriteLine("{0}----->{1}", client.Client.LocalEndPoint, client.Client.RemoteEndPoint);
                    NetworkStream ns = client.GetStream();
                    Byte[] buffer = new Byte[1024];
                    string data = "this is test";
                    buffer = ASCIIEncoding.ASCII.GetBytes(data);
                    ns.Write(buffer,0,data.Length);
                    Console.WriteLine("send:"+data+"\n");
                    
                }
            }
             
            catch(Exception ex)
            {
                Console.WriteLine("connect error"+ex.Message);
                //return;
            }
            */
            TcpClient clienttcp = new TcpClient();
            clienttcp.Connect("localhost", 8500);
            Console.WriteLine("{0}----->{1}", clienttcp.Client.LocalEndPoint, clienttcp.Client.RemoteEndPoint);
            NetworkStream nstcp = clienttcp.GetStream();
            StreamReader SR = new StreamReader(nstcp);
            StreamWriter SW = new StreamWriter(nstcp);
            while (true)
            {
                
                Random rd = new Random();
                byte da = (byte)rd.Next(65, 68);
                byte[] readda = new byte[1024];
                readda[0] = da;
                //nstcp.Write(readda,0,1);
                string str = ASCIIEncoding.ASCII.GetString(readda).Substring(0,1);
                //Console.WriteLine("send:"+str);
                
                SW.WriteLine(str);
                SW.Flush();
                //Console.ReadLine();
                //Byte[] buffer = new Byte[1024];
                //string data = "this is test";
                //buffer = ASCIIEncoding.ASCII.GetBytes(data);
                //nstcp.Write(buffer, 0, data.Length);
                //Console.WriteLine("send:"+data);
                
                //int datalen = clienttcp.Available;
                //byte[]receivedata = new byte[2048];
                //nstcp.Read(receivedata,0,datalen);
                string rcdata = SR.ReadLine();
                //string rcdata = ASCIIEncoding.ASCII.GetString(receivedata).Substring(0,datalen);
                Console.WriteLine("receive:"+rcdata);
                
            }
             
            /* Q键退出
            Console.WriteLine("\n\nQ键退出");
            ConsoleKey key;
            do
            {
                key = Console.ReadKey().Key;
            }while(key!=ConsoleKey.Q);
            */
        }
    }
}
运行结果避免了消息边界的问题产生

TCP协议发送和接受文本消息_第2张图片


你可能感兴趣的:(TCP协议发送和接受文本消息)