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

来源:互联网 发布:证书服务器开放的端口 编辑:程序博客网 时间:2024/06/05 02:28

引用总结:

对于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);            */        }    }}

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



下面用类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);            */        }    }}
运行结果避免了消息边界的问题产生




0 0
原创粉丝点击