您的位置:首页 > 理论基础 > 计算机网络

利用多线程实现网络通信

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

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

服务器端的主要代码:

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("----------------------------------");

}

}

}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  职场 休闲 网络编程