服务器端代码:
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Text;
- using System.Net;
- using System.Net.Sockets;
- using System.Threading;
- namespace multithreadservTest
- {
- class Threadtcpserver
- {
- /* 本程序中采用了多线程技术,可以应付多客户的需求。首先,程序的主线程也就是程序的入口即Main()函数,
- * 当执行到Accept方法时,线程变会阻塞;当有新连接时,就创建相应的消息服务线程。而主程序则继续进行监听,
- * 检查有没有新的连接进入。如果客户端有向服务器连接的请求,那么就把连接句柄传递给接收的套接字。由于线程
- * 的调度和切换是非常快的,快得足以让我们分辨不出程序的运行顺序,所以从宏观上来讲,可以说程序是并行执行
- * 的。但事实上,从微观的角度上说,只是cpu飞快地调度线程,让我们感觉好像可以同时接收连接和处理消息一样,
- * 但在一个时刻,只有一个线程是处于运行状态的。
- */
- /// <summary>
- /// 下面这段代码的业务逻辑是:
- /// (1)创建套接字server,并将其与本地终结点iep进行绑定。然后,在13000端口上监听是否
- 有新的客户端进行连接
- /// (2)在无限循环中有一个阻塞的方法Accept,该方法直到有新客户端连接到服务器上时,把
- 客户端的套接字信息传递给client对象。否则,将阻塞 直到有客户机进行连接。
- /// (3)ClientThread类负责客户端与服务器端之间的通信。先把客户端的套接字句柄传递给
- /// 负责消息服务的ClientThread类。然后,把ClientThread类 的ClientService方
- 法委托给线程,并启动线程。
- /// </summary>
- private Socket server;
- public Threadtcpserver()
- {
- //初始化IP地址
- IPAddress local=IPAddress.Parse("192.168.5.187");
- IPEndPoint iep = new IPEndPoint(local, 13000);
- server = new Socket(AddressFamily.InterNetwork, SocketType.Stream,
- ProtocolType.Tcp);
- //将套接字与本地终结点绑定
- server.Bind(iep);
- //在本地13000端口号上进行监听
- server.Listen(20);
- Console.WriteLine("等待客户机进行连接......");
- while (true)
- {
- //得到包含客户端信息的套接字
- Socket client = server.Accept();
- //创建消息服务线程对象
- ClientThread newclient = new ClientThread(client);
- //把ClientThread类的ClientService方法委托给线程
- Thread newthread = new Thread(new ThreadStart(newclient.ClientService));
- //启动消息服务线程
- newthread.Start();
- }
- }
- /// <summary>
- /// (1)在构造函数中得到接收到的客户套接字client,以后就通过service句柄处理消息的接收
- /// 和发送。
- /// (2)ClientService方法是委托给线程的,此方法进行消息的处理工作。在这里实现的功能是,
- /// 先从客户端接收一条消息,然后把这条消息转换为大写字母,并立即发送一条应答的消息,
- /// 也就是所谓的echo技术,通常用来进行消息之间的传递。
- /// (3)还有就是通过connections变量来记录活动的连接数。当有新增连接或断开连接的情况发
- /// 生时,都会体现出connections的变化。
- /// </summary>
- public class ClientThread
- {
- //connections变量表示连接数
- public static int connections = 0;
- public Socket service;
- int i;
- //构造函数
- public ClientThread(Socket clientsocket)
- {
- //service对象接管对消息的控制
- this.service = clientsocket;
- }
- public void ClientService()
- {
- String data = null;
- byte[] bytes = new byte[1024];
- //如果Socket不是空,则连接数加1
- if (service != null)
- {
- connections++;
- }
- Console.WriteLine("新客户连接建立:{0}个连接数", connections);
- while((i=service.Receive(bytes))!=0)
- {
- data = System.Text.Encoding.ASCII.GetString(bytes, 0, i);
- Console.WriteLine("收到的数据:{0}", data);
- //处理客户端发来的消息,这是转化为大写字母
- data = data.ToUpper();
- byte[] msg = System.Text.Encoding.ASCII.GetBytes(data);
- //发送一条应答消息
- service.Send(msg);
- Console.WriteLine("发送的数据:{0}", data);
- }
- //关闭套接字
- service.Close();
- connections--;
- Console.WriteLine("客户关闭连接:{0}个连接数", connections);
- }
- /// <summary>
- /// Main函数十分简单,生成和一个Threadtcpserver实例,然后构造函数就会一步一步地
- /// 展开,开始执行具体的业务逻辑。
- /// </summary>
- /// <param name="args"></param>
- static void Main(string[] args)
- {
- Threadtcpserver instance = new Threadtcpserver();
- }
- }
- }
- }
客户端代码:
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Text;
- using System.Net;
- using System.Net.Sockets;
- namespace multithreadclientTest
- {
- class Program
- {
- /// <summary>
- /// 本程序代码的主要功能:
- /// (1)创建套接字,并通过connect方法连接到本地终结点。当连接建立以后,便可以与服务器进
- /// 行通讯了。
- /// (2)在客户端上等待用户输入一条消息,该消息会发送到服务器创建的消息服务线程上
- /// 的ClientService 方法上进行处理。在将该消息转化为大写字母后,发还给客户端。
- /// 这是一个echo技术。如果在控制台上输入exit 接断开与服务器之间的连接。
- /// </summary>
- /// <param name="args"></param>
- static void Main(string[] args)
- {
- Socket client;
- byte[] buf = new byte[1024];
- string input;
- IPAddress local = IPAddress.Parse("192.168.5.187");
- IPEndPoint iep = new IPEndPoint(local, 13000);
- try
- {
- client = new Socket(AddressFamily.InterNetwork, SocketType.Stream,
- ProtocolType.Tcp);
- client.Connect(iep);
- }
- catch (SocketException)
- {
- Console.WriteLine("无法连接到服务器!");
- return;
- }
- finally
- {
- }
- while (true)
- {
- //在控制台上输入一条消息
- input = Console.ReadLine();
- //输入exit,可以断开与服务器的连接
- if (input == "exit")
- {
- break;
- }
- client.Send(Encoding.ASCII.GetBytes(input));
- //得到实际收到的字节总数
- int rec = client.Receive(buf);
- Console.WriteLine(Encoding.ASCII.GetString(buf, 0, rec));
- }
- Console.WriteLine("断开与服务器的连接......");
- client.Close();
- }
- }
- }
程序执行部分截图: