近来的学习让我明白程序也是循序渐进的,是一个人的思想足步成熟完善的过程,实现的功能也越来越完善,自己现在缺的不仅是思想还有实现思想的理论和技术,感觉程序的学习就像愚公移山,理论技术就在那里,看你怎么去一点点的去挖走去填充自己,可怜我这把小锄头不知道要挖到什么时候 什么时候才能挖出一点深度。默默的等候这个过程吧。下面来一步步实现服务器和客户端的通信:

首先我们做一个一个服务器端和一个客户端的通信,客户端和服务器端可以相互发送和接受数据

服务器端的主要代码:

static void Main(string[] argd)

{

           Console.WriteLine("server");

           TcpListener server = new TcpListener(IPAddress.Parse("192.168.0.114"), 9999);//服务器端要进行监听 需要两个参数:IP地址和端口号  服务器和客户端的IP必须一致 客户端的IP要和服务器的一致 建立完连接后就不再使用 但是一直会在线程堆栈中存放着 因为while循环是个死循环 main方法不会结束
            server.Start();//开始侦听传入的连接请求
            //TcpClient client = server.AcceptTcpClient();//接受客户端连接 放到这里但是只能连接一次 如果想一个服务器端给多个客户端发送 则要把所有的客户端网络流放到一个集合里面
             NetworkStream netstream = client.GetStream();//利用网络流读取客户端信息

          Thread th = new Thread(ReadText);
            th.Start(netstream);
            StreamWriter swriter = new StreamWriter(netstream);//利用文件流来发送数据
            while (true)
            {
                Console.WriteLine("---------------------------");
                string con = Console.ReadLine();
                swriter.WriteLine(con);
                swriter.Flush();
                Console.WriteLine("服务:" + DateTime.Now);
                Console.WriteLine("---------------------------");
            }
        }
        static void ReadText(object o)//接受数据
        {
            NetworkStream netstream = o as NetworkStream;//as的用法:as   运算符用于执行可兼容类型之间的转换。用法:expression   as   type 


            StreamReader sr = new StreamReader(netstream);
            while (true)
            {
                Console.WriteLine("---------------------------");
                string con = sr.ReadLine();
                Console.WriteLine(con);
                Console.WriteLine("客户:" + DateTime.Now);
                Console.WriteLine("---------------------------");
            }

        }

 

}

客户端:

 static void Main(string[] args)
        {
            Console.WriteLine("client");
            TcpClient client = new TcpClient("192.168.0.10", 9999);
            NetworkStream netstream = client.GetStream();
            StreamWriter swriter = new StreamWriter(netstream);
            Thread th = new Thread(ReadText);
            th.Start(netstream);
            while (true)
            {
                Console.WriteLine("---------------------------");
                string con = Console.ReadLine();            
                swriter.WriteLine(con);
                swriter.Flush();
                Console.WriteLine("客户:" + DateTime.Now);
                Console.WriteLine("---------------------------");
            }

        }
        static void ReadText(object o)
        {
            NetworkStream netstream = o as NetworkStream;
            StreamReader sr = new StreamReader(netstream);
            while (true)
            {
                string con = sr.ReadLine();
                Console.WriteLine("---------------------------");
                Console.WriteLine(con);
                Console.WriteLine("服务:" + DateTime.Now);
                Console.WriteLine("---------------------------");
            }

        }

对程序进一步的改进,一个服务器端,多个客户端

多个客户端的通信要考虑如何存放客户端数据呢?存储多个动态数据考虑到用集合或者是哈希表 哈希表的好处是可以分别获取键和值,首先我们使用集合来存储接受的多个客户端:

服务器端:(客户端没有改变,代码如上)

 

namespace Server
{
    class Program
    {
        static List<NetworkStream> tcpclients = new List<NetworkStream>();//如果想一个服务器端给多个客户端发送 则要把所有的客户端网络流放到一个集合里面

        static void Main(string[] args)
        {
            //一个客户端接受一个服务器端
            Console.WriteLine("server");
            TcpListener server = new TcpListener(IPAddress.Parse("192.168.0.114"), 9999  );       

server.Start();//开始侦听传入的连接请求
                     Thread th2 = new Thread(AcceptClient);
            th2.Start(server);

            while (true)
            {
                Console.WriteLine("开始传输数据");
                Console.ReadLine();//必须有这一行 不然直接运行请选择客户端这一行了
                for (int i = 0; i < tcpclients.Count; i++)//遍历客户端 并给客户端编号 按着先后运行的顺序
                {
                    Console.WriteLine("{0}客户端", i + 1);

                }
                Console.WriteLine("请选择客户端:");
                int re = int.Parse(Console.ReadLine()) - 1;
                NetworkStream stream = tcpclients[re];//将输入的客户端存入到网络流中 并开始想给客户端写数据
                StreamWriter sw = new StreamWriter(stream);//想选定的客户端传入数据
                while (true)
                {
                    Console.WriteLine("请输入要传输的内容");

                    Console.WriteLine("----------------------------------");
                    string con = Console.ReadLine();//阻塞
                    sw.WriteLine(con);
                    sw.Flush();
                    Console.WriteLine("服务:" + DateTime.Now);
                    Console.WriteLine("----------------------------------");
                    Console.WriteLine("退出请按E,否则请按其他键");
                    if (Console.ReadLine().ToUpper() == "E")
                    {
                        break;
                    }
                }

            }
        }
        static void ReadText(object o)
        {
            try
            {
                NetworkStream netstream = o as NetworkStream;
                StreamReader sr = new StreamReader(netstream);
                while (true)
                {
                    Console.WriteLine("----------------------------------");
                    string con = sr.ReadLine();
                    Console.WriteLine(con);
                    Console.WriteLine("客户:" + DateTime.Now);
                    Console.WriteLine("----------------------------------");
                }
            }
            catch
            {
                throw new Exception("服务器端断开");
            }


        }
        /// <summary>
        /// 定义一个线程来读取网络流中的数据
        /// </summary>
        /// <param name="o"></param>
        static void AcceptClient(object o)
        {
            TcpListener server = o as TcpListener;
            while (true)
            {
                TcpClient client = server.AcceptTcpClient();
                NetworkStream netstream = client.GetStream();
                tcpclients.Add(netstream);//将网络流加入要客户端网络流这个集合里
                Thread th1 = new Thread(ReadText);//起一个线程读取客户端数据

                th1.Start(netstream);
            }


        }
    }
}

使用哈希表来存储接收的客户端

namespace Server
{
    class Program
    {
        static Dictionary<string, NetworkStream> tcpclients = new Dictionary<string, NetworkStream>();
        static void Main(string[] args)
        {
            Console.WriteLine("server");
            TcpListener server = new TcpListener(IPAddress.Parse("192.168.0.10"), 9999);
            server.Start();

            Thread th = new Thread(AcceptClient);
            th.Start(server);

            Console.WriteLine("开始发送请按任意键!");
            Console.ReadLine();
            while (true)
            {

                foreach (string s in tcpclients.Keys)
                {
                    Console.WriteLine(s);
                }
                Console.WriteLine("请选择客户端:");
                string key = Console.ReadLine();
                NetworkStream stream = tcpclients[key];
                StreamWriter swriter = new StreamWriter(stream);
                while (true)
                {
                    Console.WriteLine("请输入发送内容:");
                    string con = Console.ReadLine();
                    swriter.WriteLine(con);
                    swriter.Flush();
                    Console.WriteLine("退出请按E,否则请按其他键");
                    if (Console.ReadLine().ToUpper() == "E")
                    {
                        break;
                    }
                }
            }

        }
        static void AcceptClient(object o)
        {
            TcpListener server = o as TcpListener;
            while (true)
            {
                TcpClient clinet = server.AcceptTcpClient();
                NetworkStream netstream = clinet.GetStream();         
            
                StreamReader sr = new StreamReader(netstream);
                string con = sr.ReadLine();


                tcpclients.Add(con, netstream);


                Thread th = new Thread(ReadText);
                th.Start(netstream);

            }
        }
        static void ReadText(object o)
        {
            NetworkStream netstream = o as NetworkStream;
            StreamReader sr = new StreamReader(netstream);
            while (true)
            {
                Console.WriteLine("---------------------------");
                string con = sr.ReadLine();
                Console.WriteLine(con);
                Console.WriteLine("客户:" + DateTime.Now);
                Console.WriteLine("---------------------------");
            }


        }
    }
}

进一步的实现就是利用服务器中转实现两个客户端的通信:

服务器端:获取客户端的端口号 然后接受客户端的发送的包 可以规定客户端发送格式为:发信人|收信人|内容 服务器端接收客户端的消息后进行处理 用数组的Splict方法得到 收信人 内容 然后赋给一个网络流对象 然后通过StreamWriter写入 并发送给收信人

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.Net.Sockets;
using System.IO;
using System.Threading;


namespace Server
{
    class Program
    {
        static Dictionary<string, NetworkStream> tcpclients = new Dictionary<string, NetworkStream>();
        static void Main(string[] args)
        {
            Console.WriteLine("server");
            TcpListener server = new TcpListener(IPAddress.Parse("192.168.0.114"), 9999);
            server.Start();
            Thread th2 = new Thread(AcceptClient);
            th2.Start(server);

           

        }
        static void AcceptClient(object o)
        {
            TcpListener server = o as TcpListener;
            while (true)
            {
                TcpClient client = server.AcceptTcpClient();
                NetworkStream netstream = client.GetStream();
                StreamReader sr = new StreamReader(netstream);
                string con = sr.ReadLine();
                tcpclients.Add(con, netstream);
                Thread th1 = new Thread(ReadText);
                th1.Start(netstream);
            }
        }
        static void ReadText(object o)
        {
            NetworkStream netstream = o as NetworkStream;
            StreamReader sr = new StreamReader(netstream);
            while (true)
            {
                string con=  sr.ReadLine();
                Console.WriteLine(con);
                string[] conn= con.Split('|');
                NetworkStream stream = tcpclients[conn[1]];
                StreamWriter sw = new StreamWriter(stream);
                sw.WriteLine(conn[0]+"|"+conn[2]);
                sw.Flush();
                Console.WriteLine("客户端" + DateTime.Now);

            }

        }
    }
}
 

客户端:客户端发送数据以发信人|收信人|内容的格式发送

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.Net.Sockets;
using System.IO;
using System.Threading;

namespace Client
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("client");
            TcpClient client = new TcpClient("192.168.0.114", 9999);//连接客户端
            NetworkStream netstream = client.GetStream();//利用网络流写入

            //客户端写
            StreamWriter sw = new StreamWriter(netstream);
            Console.WriteLine("请输入名称");
            string con1 = Console.ReadLine();
            sw.WriteLine(con1);
            sw.Flush();
            Thread th = new Thread(ReadText);//利用线程控制 客户端读入
            th.Start(netstream);
             
            while (true)
            {
                Console.WriteLine("请输入自己的发送名称:");
                string con = Console.ReadLine(); 
                Console.WriteLine("请输入接受名称:");
                con += "|" + Console.ReadLine();
                Console.WriteLine("请输入发送内容:");
                con+= "|" + Console.ReadLine();
                sw.WriteLine(con);
                sw.Flush();
                Console.WriteLine("客户端" + DateTime.Now);
                Console.WriteLine("----------------------------------");
            }

        }
        static void ReadText(object o)
        {
            NetworkStream netstream = o as NetworkStream;
            StreamReader sr = new StreamReader(netstream);
            while (true)
            {

                Console.WriteLine("----------------------------------");
                string con = sr.ReadLine();
                Console.WriteLine(con);
                Console.WriteLine("服务器:" + DateTime.Now);

                Console.WriteLine("----------------------------------");
            }
        }
    }
}