Server.cs 服务端程序
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Text; using System.Windows.Forms; using System.Threading; using System.Net; using System.Net.Sockets; namespace SocketTest { public partial class Server : Form { Thread serverThread; //服务端线程 Thread clientThread; //客户端线程 Socket serverSocket; //服务端socket Socket clientSocket; //客户端socket public Server() { InitializeComponent(); } private void ServerStart() { //创建IPEndPoint实例 IPEndPoint ipep = new IPEndPoint(IPAddress.Any, 6001); //创建一个套接字 serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); //将所创建的套接字与IPEndPoint绑定 serverSocket.Bind(ipep); //设置套接字为收听模式 serverSocket.Listen(10); /** * 通过serverSocket.Accept()来接收客户Socket的连接请求, * 在这里用循环可以实现该线程实时侦听,而不是只侦听一次。 * 当程序运行serverSocket.Accept()时,会等待,直到有客户端Socket发起连接请求时, * 获取该客户Socket,如上面的clientSocket。在这里我用多线程来实现与多个客户端Socket的连接和通信, * 一旦接收到一个连接后,就新建一个线程,执行ReceiveData功能来实现信息的发送和接收。 */ while (true) { try { //在套接字上接收接入的连接 clientSocket = serverSocket.Accept(); clientThread = new Thread(new ThreadStart(ReceiveData)); clientThread.Start(); } catch (Exception ex) { MessageBox.Show("listening Error: " + ex.Message); } } } /** * 通过IPEndPoint clientep = (IPEndPoint)s.RemoteEndPoint; * 我们可以获取连接上的远程主机的端口和IP地址,如果想查询该主机的其它属性如主机名等, * 可用于上一篇讲的Dns.GetHostByAddress(string ipAddress)来返回一个IPHostEntry对象,就可以得到。 * 另外我们要注意的是,通过Socket发送信息,必须要先把发送的信息转化成二进字进行传输, * 收到信息后也要把收到的二进字信息转化成字符形式, * 这里可以通过Encoding.ASCII.GetBytes(welcome);和Encoding.ASCII.GetString(buffer).Substring(0, bufLen);来实现。 * 以上就是服务端Socket侦听模式的实现,只要有远程客户端Socket连接上后,就可以轻松的发送信息和接收信息了。 * 下面我们来看看客户端Socket是怎么连接上服务器的。 **/ private void ReceiveData() { bool keepalive = true; Socket s = clientSocket; Byte[] buffer = new Byte[1024]; //根据收听到的客户端套接字向客户端发送信息 IPEndPoint clientep = (IPEndPoint)s.RemoteEndPoint; this.Invoke(new MethodInvoker(() => { lstServer.Items.Add("Client:" + clientep.Address + "(" + clientep.Port + ")"); })); string welcome = "Welcome to my test sever "; byte[] data = new byte[1024]; data = Encoding.ASCII.GetBytes(welcome); s.Send(data, data.Length, SocketFlags.None); while (keepalive) { //在套接字上接收客户端发送的信息 int bufLen = 0; try { bufLen = s.Available; s.Receive(buffer, 0, bufLen, SocketFlags.None); if (bufLen == 0) continue; } catch (Exception ex) { MessageBox.Show("Receive Error:" + ex.Message); return; } clientep = (IPEndPoint)s.RemoteEndPoint; string clientcommand = System.Text.Encoding.ASCII.GetString(buffer).Substring(0, bufLen); this.Invoke(new MethodInvoker(() => { lstServer.Items.Add(clientcommand + "(" + clientep.Address + ":" + clientep.Port + ")"); })); } } private void btnOpen_Click(object sender, EventArgs e) { serverThread = new Thread(new ThreadStart(ServerStart)); serverThread.Start(); lstServer.Items.Add("Server Start ....."); } } }
Client.cs(客户端程序)
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Text; using System.Windows.Forms; using System.Net; using System.Net.Sockets; using System.Threading; namespace Client { public partial class Client : Form { Socket clientSocket; Thread clientThread; public Client() { InitializeComponent(); } /** * 客户端Socket连接相对来说比较简单了,另外说明一下,在执行客户端连接前,服务端Socket侦听必须先启动, * 不然会提示服务器拒绝连接的信息。 * 客户端的发送信息和接收信息跟服务器的接收发送是一样的,只不过一个是侦听模式而另一个是连接模式。 * 另外提一下,这里服务端开启侦听服务、客户端连接服务端都采用线程方式来实现,这样服务端能够跟多个客户端同时通信,不用等候, * 当然还有另外一种方式可以实现那就是异步socket. */ private void ConnectToServer() { byte[] data = new byte[1024]; //创建一个套接字 IPEndPoint ipep = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 6001); clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); //将套接字与远程服务器地址相连 try { clientSocket.Connect(ipep); } catch (SocketException ex) { MessageBox.Show("connect error: " + ex.Message); return; } while (true) { //接收服务器信息 int bufLen = 0; try { bufLen = clientSocket.Available; clientSocket.Receive(data, 0, bufLen, SocketFlags.None); if (bufLen == 0) { continue; } } catch (Exception ex) { MessageBox.Show("Receive Error:" + ex.Message); return; } string clientcommand = System.Text.Encoding.ASCII.GetString(data).Substring(0, bufLen); this.Invoke(new MethodInvoker(() => { lstClient.Items.Add(clientcommand); })); //clientSocket.Shutdown(SocketShutdown.Both); //clientSocket.Close(); } } private void button1_Click(object sender, EventArgs e) { clientThread = new Thread(new ThreadStart(ConnectToServer)); clientThread.Start(); } private void btnSend_Click(object sender, EventArgs e) { //向服务器发送信息 byte[] data = new byte[1024]; data = Encoding.ASCII.GetBytes(txtClient.Text); clientSocket.Send(data, data.Length, SocketFlags.None); } } }