C#中的socket编程入门实例
来源:互联网 发布:bind javascript 编辑:程序博客网 时间:2024/05/16 00:41
Socket主要是通过TCP或者UDP协议进行多台主机之间的通讯。由于项目中用到,所以今天就结合项目需求对socket编程的C#表示进行一步一步详细的介绍。
TCP的详细过程我就不多介绍了,这个是网络基础,不明白的同学可以看TCP
开启服务端对端口的监听
我们都知道TCP服务端需要对某个端口进行连续监听,客户端才可以发起连接。所以我们先讲讲服务端如何打开端口进行监听。
新建一个控制台应用程序ServerConsole,引用System.Net
和System.Net.Sockets
。
代码如下:
using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Net;using System.Net.Sockets;namespace ServerConsole{ class Program { static void Main(string[] args) { Console.WriteLine("Server is running..."); IPAddress ip = IPAddress.Parse("127.0.0.1");//获取ip地址 TcpListener listener = new TcpListener(ip, 8500); listener.Start();//开始监听 Console.WriteLine("Start Listening..."); Console.WriteLine("\n\n 输入 \"Q\"键退出。"); ConsoleKey key; do { key = Console.ReadKey(true).Key; } while (key != ConsoleKey.Q); } }}
运行后,通过cmd netstat –a 可以查看已经开启8500端口监听:
客户端与服务器连接
服务端开启端口监听后,接下来就是客户端来发起连接了。
创建一个新的控制台命令程序ClientConsole,代码如下:
using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Net;using System.Net.Sockets;namespace ClientConsole{ class Program { static void Main(string[] args) { Console.WriteLine("Client Running..."); TcpClient client = new TcpClient(); try { client.Connect("localhost", 8500);//与服务器连接 } catch (Exception ex){ Console.WriteLine(ex.Message); return; } //打印连接到的服务器信息 Console.WriteLine("Server Connected! {0}-->{1}", client.Client.LocalEndPoint, client.Client.RemoteEndPoint); //按Q退出 Console.WriteLine("\n\n 输入 \"Q\"键退出。"); ConsoleKey key; do { key = Console.ReadKey(true).Key; } while (key != ConsoleKey.Q); } }}
当我们同时运行服务端ServerConsole和客户端ClientConsole后,客户端程序效果:
可以看到,客户端开启了55279端口和服务端成功建立连接。客户端使用的端口号是随机选取的,并不需要我们来设置,并且每次运行时,端口都不同。8500端口和客户端建立连接后,仍然处于监听状态,也就是说一个端口可以和多个远程端口进行通信。
服务端和客户端通信
连接已经成功建立了,接下来需要进行的就是通信了。
由于这里只是入门介绍,所以不涉及到文件的传输,我们主要还是介绍字节流的传输过程。
客户端发送,服务端接收
我们先从一条数据开始循序渐进吧。
服务端Server代码如下:
using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Net;using System.Net.Sockets;namespace Server{ class Program { static void Main(string[] args) { const int BufferSize = 8192;//缓存大小,8192字节,可以保存4096个汉字和英文字符 Console.WriteLine("Server is running ..."); IPAddress ip = IPAddress.Parse("127.0.0.1");//获取ip地址 TcpListener listener = new TcpListener(ip, 8500); listener.Start();//开始监听 Console.WriteLine("Start Listening..."); //获取一个连接,中断方法 TcpClient remoteClient = listener.AcceptTcpClient(); //打印连接到的客户端信息 Console.WriteLine("Client Connected! {0}<--{1}", remoteClient.Client.LocalEndPoint, remoteClient.Client.RemoteEndPoint); //获取流,并写入buffer中 NetworkStream streamToClient = remoteClient.GetStream(); byte[] buffer = new byte[BufferSize]; int bytesRead = streamToClient.Read(buffer, 0, BufferSize);//一直等待客户端传信息 Console.WriteLine("Reading data,{0} bytes...", bytesRead); //获得请求的字符串 string msg = Encoding.Unicode.GetString(buffer, 0, bytesRead); Console.WriteLine("Received:{0}", msg); //按Q退出 Console.WriteLine("\n\n 输入 \"Q\"键退出。"); ConsoleKey key; do { key = Console.ReadKey(true).Key; } while (key != ConsoleKey.Q); } }}
可以看到,我们利用服务端监听客户端传入字节流,将其放入缓存并输出。
客户端代码如下:
using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Net;using System.Net.Sockets;namespace Client{ class Program { static void Main(string[] args) { Console.WriteLine("Client Running..."); TcpClient client = new TcpClient(); try { client.Connect("localhost", 8500);//与服务器连接 } catch (Exception ex) { Console.WriteLine(ex.Message); return; } //打印连接到的服务器信息 Console.WriteLine("Server Connected! {0}-->{1}", client.Client.LocalEndPoint, client.Client.RemoteEndPoint); //定义要传送的信息 string msg = "\"欢迎连接到服务器!\""; NetworkStream streamToServer = client.GetStream(); //发送信息 byte[] buffer = Encoding.Unicode.GetBytes(msg);//获得缓存 streamToServer.Write(buffer, 0, buffer.Length);//发往服务器 Console.WriteLine("Sent:{0}", msg); //按Q退出 Console.WriteLine("\n\n 输入 \"Q\"键退出。"); ConsoleKey key; do { key = Console.ReadKey(true).Key; } while (key != ConsoleKey.Q); } }}
这里是NetworkStream 类型就是字节流传输的一个载体。我们将客户端程序中定义好的字符串“欢迎连接到服务器!”传输给服务端。
客户端效果如下:
服务端效果如下:
可以看到服务端成功接收客户端信息。
客户端发送多条,服务端接收多条
再来看看我们如何一次发送多个信息到服务器。
服务端ServerMany代码如下:
using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Net;using System.Net.Sockets;namespace ServerMany{ class Program { static void Main(string[] args) { const int BufferSize = 8192;//缓存大小,8192字节,可以保存4096个汉字和英文字符 Console.WriteLine("Server is running ..."); IPAddress ip = IPAddress.Parse("127.0.0.1");//获取ip地址 TcpListener listener = new TcpListener(ip, 8500); listener.Start();//开始监听 Console.WriteLine("Start Listening..."); do { //获取一个连接,中断方法 TcpClient remoteClient = listener.AcceptTcpClient(); //打印连接到的客户端信息 Console.WriteLine("Client Connected! {0}<--{1}", remoteClient.Client.LocalEndPoint, remoteClient.Client.RemoteEndPoint); //获取流,并写入buffer中 NetworkStream streamToClient = remoteClient.GetStream(); byte[] buffer = new byte[BufferSize]; int bytesRead = streamToClient.Read(buffer, 0, BufferSize);//一直等待客户端传信息 Console.WriteLine("Reading data,{0} bytes...", bytesRead); //获得请求的字符串 string msg = Encoding.Unicode.GetString(buffer, 0, bytesRead); Console.WriteLine("Received:{0}", msg); } while (true); //按Q退出 Console.WriteLine("\n\n 输入 \"Q\"键退出。"); ConsoleKey key; do { key = Console.ReadKey(true).Key; } while (key != ConsoleKey.Q); } }}
我们通过do while循环一直等待客户端传输信息。
客户端ClientMany代码如下:
using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Net;using System.Net.Sockets;namespace ClientMany{ class Program { static void Main(string[] args) { Console.WriteLine("Client Running..."); TcpClient client; //启动多个服务器 for (int i = 0; i < 5; i++) { try { client = new TcpClient(); client.Connect("localhost", 8500);//与服务器连接 } catch (Exception ex) { Console.WriteLine(ex.Message); return; } //打印连接到的服务器信息 Console.WriteLine("Server Connected! {0}-->{1}", client.Client.LocalEndPoint, client.Client.RemoteEndPoint); //定义要传送的信息 string msg = "\"欢迎连接到服务器!\""; NetworkStream streamToServer = client.GetStream(); //发送信息 byte[] buffer = Encoding.Unicode.GetBytes(msg);//获得缓存 streamToServer.Write(buffer, 0, buffer.Length);//发往服务器 Console.WriteLine("Sent:{0}", msg); } //按Q退出 Console.WriteLine("\n\n 输入 \"Q\"键退出。"); ConsoleKey key; do { key = Console.ReadKey(true).Key; } while (key != ConsoleKey.Q); } }}
这里我们先通过一个for循环传输多条数据。
客户端效果如下:
服务端效果如下:
客户端发送自定义信息,服务端接收自定义信息
前面的demo中我们发送的信息都是固定在程序中的。现在我们对其进行改进,使客户端可以发送自定义的信息。
服务端ServerManySelf
代码如下:
using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Net;using System.Net.Sockets;namespace ServerManySelf{ class Program { static void Main(string[] args) { const int BufferSize = 8192;//缓存大小,8192字节,可以保存4096个汉字和英文字符 Console.WriteLine("Server is running ..."); IPAddress ip = IPAddress.Parse("127.0.0.1");//获取ip地址 TcpListener listener = new TcpListener(ip, 8500); listener.Start();//开始监听 Console.WriteLine("Start Listening..."); //获取一个连接,中断方法 TcpClient remoteClient = listener.AcceptTcpClient(); //打印连接到的客户端信息 Console.WriteLine("Client Connected! {0}<--{1}", remoteClient.Client.LocalEndPoint, remoteClient.Client.RemoteEndPoint); //获取流,并写入buffer中 NetworkStream streamToClient = remoteClient.GetStream(); do { byte[] buffer = new byte[BufferSize]; int bytesRead = streamToClient.Read(buffer, 0, BufferSize);//一直等待客户端传信息 Console.WriteLine("Reading data,{0} bytes...", bytesRead); //获得请求的字符串 string msg = Encoding.Unicode.GetString(buffer, 0, bytesRead); Console.WriteLine("Received:{0}", msg); } while (true); //按Q退出 Console.WriteLine("\n\n 输入 \"Q\"键退出。"); ConsoleKey key; do { key = Console.ReadKey(true).Key; } while (key != ConsoleKey.Q); } }}
服务端的代码基本没有什么变化,客户端ClientManySelf
代码如下:
using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Net;using System.Net.Sockets;namespace ClientManySelf{ class Program { static void Main(string[] args) { Console.WriteLine("Client Running..."); TcpClient client; //启动多个服务器 for (int i = 0; i < 5; i++) { try { client = new TcpClient(); client.Connect("localhost", 8500);//与服务器连接 } catch (Exception ex) { Console.WriteLine(ex.Message); return; } //打印连接到的服务器信息 Console.WriteLine("Server Connected! {0}-->{1}", client.Client.LocalEndPoint, client.Client.RemoteEndPoint); NetworkStream streamToServer = client.GetStream(); ConsoleKey key; Console.WriteLine("Menu:S-Send,X-Exit"); do { key = Console.ReadKey(true).Key; if (key == ConsoleKey.S) { //获取输入的字符串 Console.Write("输入信息:"); string msg = Console.ReadLine(); //发送信息 byte[] buffer = Encoding.Unicode.GetBytes(msg);//获得缓存 streamToServer.Write(buffer, 0, buffer.Length);//发往服务器 Console.WriteLine("Sent:{0}", msg); } } while (key != ConsoleKey.X); } } }}
我们通过交互来完成客户端的输入,从而发送自定义的信息到服务端。
客户端效果:
服务端效果:
服务端回发信息,客户端接收
TCP是双向通信的,前面一直介绍的是客户端发送信息到服务端,接下来介绍如何从服务端发送信息到客户端。
服务端通过Read方法读信息,所以通过Write方法写信息。
我们想象一个需求,就是服务端将客户端发送过来的字符串变为大写后再传输回客户端。
服务端ServerSend代码如下:
using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Net;using System.Net.Sockets;namespace ServerSend{ class Program { static void Main(string[] args) { const int BufferSize = 8192;//缓存大小,8192字节,可以保存4096个汉字和英文字符 Console.WriteLine("Server is running ..."); IPAddress ip = IPAddress.Parse("127.0.0.1");//获取ip地址 TcpListener listener = new TcpListener(ip, 8500); listener.Start();//开始监听 Console.WriteLine("Start Listening..."); //获取一个连接,中断方法 TcpClient remoteClient = listener.AcceptTcpClient(); //打印连接到的客户端信息 Console.WriteLine("Client Connected! {0}<--{1}", remoteClient.Client.LocalEndPoint, remoteClient.Client.RemoteEndPoint); //获取流,并写入buffer中 NetworkStream streamToClient = remoteClient.GetStream(); byte[] buffer = new byte[BufferSize]; int bytesRead = streamToClient.Read(buffer, 0, BufferSize);//一直等待客户端传信息 Console.WriteLine("Reading data,{0} bytes...", bytesRead); //获得请求的字符串 string msg = Encoding.Unicode.GetString(buffer, 0, bytesRead); Console.WriteLine("Received:{0}", msg); //转换成大写并发送 msg = msg.ToUpper(); buffer = Encoding.Unicode.GetBytes(msg); lock (streamToClient) { streamToClient.Write(buffer, 0, buffer.Length); } Console.WriteLine("Send:{0}", msg); //按Q退出 Console.WriteLine("\n\n 输入 \"Q\"键退出。"); ConsoleKey key; do { key = Console.ReadKey(true).Key; } while (key != ConsoleKey.Q); } }}
客户端同意通过Read方法来读,客户端ClientAccept代码如下:
using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Net;using System.Net.Sockets;namespace ClientAccept{ class Program { static void Main(string[] args) { const int BufferSize = 8192;//缓存大小,8192字节,可以保存4096个汉字和英文字符 Console.WriteLine("Client Running..."); TcpClient client; //启动多个服务器 for (int i = 0; i < 5; i++) { try { client = new TcpClient(); client.Connect("localhost", 8500);//与服务器连接 } catch (Exception ex) { Console.WriteLine(ex.Message); return; } //打印连接到的服务器信息 Console.WriteLine("Server Connected! {0}-->{1}", client.Client.LocalEndPoint, client.Client.RemoteEndPoint); NetworkStream streamToServer = client.GetStream(); ConsoleKey key; Console.WriteLine("Menu:S-Send,X-Exit"); do { key = Console.ReadKey(true).Key; if (key == ConsoleKey.S) { //获取输入的字符串 Console.Write("输入信息:"); string msg = Console.ReadLine(); //发送信息 byte[] buffer = Encoding.Unicode.GetBytes(msg);//获得缓存 streamToServer.Write(buffer, 0, buffer.Length);//发往服务器 Console.WriteLine("Sent:{0}", msg); //获取信息 int bytesRead; buffer = new byte[BufferSize]; lock (streamToServer) { bytesRead = streamToServer.Read(buffer, 0, BufferSize); } msg = Encoding.Unicode.GetString(buffer, 0, bytesRead); Console.WriteLine("Received:{0}", msg); } } while (key != ConsoleKey.X); } } }}
客户端效果如下:
服务端效果如下:
服务端指定ID,客户端对数据库进行查询
双向通信也介绍了。最后以一个我在项目中需要用到的功能来收尾。我们通过服务端发送需要查询的ID,然后客户端通过ID对Access数据库进行查询,并将结果返回给服务端。
服务端ServerSQL代码如下:
using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Net;using System.Net.Sockets;namespace ServerSQL{ class Program { static void Main(string[] args) { const int BufferSize = 8192;//缓存大小,8192字节,可以保存4096个汉字和英文字符 Console.WriteLine("Server is running ..."); IPAddress ip = IPAddress.Parse("127.0.0.1");//获取ip地址 TcpListener listener = new TcpListener(ip, 8500); listener.Start();//开始监听 Console.WriteLine("Start Listening..."); //获取一个连接,中断方法 TcpClient remoteClient = listener.AcceptTcpClient(); //打印连接到的客户端信息 Console.WriteLine("Client Connected! {0}<--{1}", remoteClient.Client.LocalEndPoint, remoteClient.Client.RemoteEndPoint); //获取流,并写入buffer中 NetworkStream streamToClient = remoteClient.GetStream(); byte[] buffer = new byte[BufferSize]; int bytesRead = streamToClient.Read(buffer, 0, BufferSize);//一直等待客户端传信息 Console.WriteLine("Reading data,{0} bytes...", bytesRead); //获得请求的字符串 string msg = Encoding.Unicode.GetString(buffer, 0, bytesRead); Console.WriteLine("Received:{0}", msg); //发送信息 ConsoleKey key; Console.WriteLine("Menu:S-Send,X-Exit"); do { key = Console.ReadKey(true).Key; if (key == ConsoleKey.S) { //获取输入的字符串 Console.Write("输入信息:"); msg = Console.ReadLine(); //发送信息 buffer = Encoding.Unicode.GetBytes(msg);//获得缓存 streamToClient.Write(buffer, 0, buffer.Length);//发往服务器 Console.WriteLine("Sent:{0}", msg); //获取流,并写入buffer中 streamToClient = remoteClient.GetStream(); buffer = new byte[BufferSize]; bytesRead = streamToClient.Read(buffer, 0, BufferSize);//一直等待客户端传信息 Console.WriteLine("Reading data,{0} bytes...", bytesRead); //获得请求的字符串 msg = Encoding.Unicode.GetString(buffer, 0, bytesRead); Console.WriteLine("Received:{0}", msg); } } while (key != ConsoleKey.X); //按Q退出 Console.WriteLine("\n\n 输入 \"Q\"键退出。"); do { key = Console.ReadKey(true).Key; } while (key != ConsoleKey.Q); } }}
客户端ClientSQL代码如下:
using System;using System.Collections.Generic;using System.Linq;using System.Text;//数据库引用using System.Data;using System.Data.OleDb;//Socket引用using System.Net;using System.Net.Sockets;namespace ClientSQL{ class Program { /// <summary> /// 数据库连接 /// </summary> /// <returns>数据库连接对象</returns> public static OleDbConnection getConn() { string connstr = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=G:\\users\\brizer\\documents\\visual studio 2010\\Projects\\socket\\test.mdb"; OleDbConnection tempconn = new OleDbConnection(connstr); return tempconn; } /// <summary> /// 获取需要的信息 /// </summary> /// <param name="id">通过参数查询</param> /// <returns>得到查询结果的字节流</returns> public static string getValueFromId(string id) { string tempValue = "";//定义返回值 try { OleDbConnection conn = getConn();//得到连接对象 string strCom = "Select * from testTable where id =" + id; OleDbCommand myCommand = new OleDbCommand(strCom, conn); conn.Open(); OleDbDataReader reader; reader = myCommand.ExecuteReader();//执行命令并得到相应的DataReader //下面将得到的值赋给tempValue对象 if (reader.Read()) { tempValue = "ID:" + reader["id"].ToString(); tempValue += "温度:" + reader["温度"].ToString(); tempValue += "长度:" + reader["长度"].ToString(); } else { tempValue = "没有该记录"; } } catch (Exception e) { } return tempValue; } /// <summary> /// 将字节流传给服务端 /// </summary> /// <param name="value">需要传送的内容</param> public static void sendToServer(string value) { const int BufferSize = 8192;//缓存大小,8192字节,可以保存4096个汉字和英文字符 Console.WriteLine("Client Running..."); TcpClient client = new TcpClient(); try { client.Connect("localhost", 8500);//与服务器连接 } catch (Exception ex) { Console.WriteLine(ex.Message); return; } //打印连接到的服务器信息 Console.WriteLine("Server Connected! {0}-->{1}", client.Client.LocalEndPoint, client.Client.RemoteEndPoint); //定义要传送的信息 string msg = value; NetworkStream streamToServer = client.GetStream(); //发送信息 byte[] buffer = Encoding.Unicode.GetBytes(msg);//获得缓存 streamToServer.Write(buffer, 0, buffer.Length);//发往服务器 Console.WriteLine("Sent:{0}", msg); //接收信息 do { buffer = new byte[BufferSize]; int bytesRead = streamToServer.Read(buffer, 0, BufferSize);//一直等待客户端传信息 Console.WriteLine("Reading data,{0} bytes...", bytesRead); //获得请求的字符串 msg = Encoding.Unicode.GetString(buffer, 0, bytesRead); Console.WriteLine("Received:{0}", msg); string result = getValueFromId(msg); Console.WriteLine("结果:{0}", result); //将结果发送给服务端 msg = result; byte[] bufferWrite = Encoding.Unicode.GetBytes(result); streamToServer.Write(bufferWrite, 0, bufferWrite.Length);//发往服务器 } while (true); //按Q退出 Console.WriteLine("\n\n 输入 \"Q\"键退出。"); ConsoleKey key; do { key = Console.ReadKey(true).Key; } while (key != ConsoleKey.Q); } static void Main(string[] args) { //获取需要的数据信息 string value; value = getValueFromId("2"); //Console.WriteLine(value); //Console.ReadKey(); //通过TCP传到服务端 sendToServer(value); } }}
Access数据库test中内容如下:
服务端效果如下:
客户端效果如下:
成功将客户端指定数据传输至服务端。
全部实例下载地址
- C#中的socket编程入门实例
- C#中的socket编程入门实例
- C#中的Socket编程
- Java socket 入门编程实例
- Java socket 入门编程实例
- Java socket 入门编程实例
- Java socket 入门编程实例
- C# Socket多线程编程实例
- C# Socket多线程编程实例
- C# Socket多线程编程实例
- C# Socket 编程简单实例
- C# Socket多线程编程实例
- C# Socket多线程编程实例
- C# Socket多线程编程实例
- C# Socket编程基础入门
- C#中的Socket编程详解
- C#中的Socket编程详解
- C#中的Socket编程详解
- OpenXml操作Word的一些操作总结.无word组件生成word.
- 修改Android Studio的代码补全快捷键,解决与输入法快捷键冲突
- VirtualBox中虚拟机突然出错,硬件加速无法开启
- Android报错解决 UIL doesn't support scheme(protocol) by default [file:/]. You should impleme
- servlet (1) 基础
- C#中的socket编程入门实例
- SpringMVC @Autowired
- how to install mqtt in linux (Linux环境下安装mosquitto)
- matlab的reshape和opencv的reshape异同
- svn 设置文件可执行权限
- 没看懂
- zepto点透研究
- Access restriction在myeclipse中遇到的访问限制的问题
- 图片的常用几种图形变换