Socket
2012-07-10 16:55 Carl Xing 阅读(352) 评论(0) 编辑 收藏 举报1、基于TCP的web服务器
windows控制台应用程序
class Program { static void Main(string[] args) { //SocketServer(); GetClientMsg(); //TcpServer(); } private static void SocketServer() { // 获得本机的Ip地址,即127.0.0.1 IPAddress localaddress =IPAddress.Loopback; // 创建可以访问的断点,49155表示端口号,如果这里设置为0,表示使用一个由系统分配的空闲的端口号 IPEndPoint endpoint = new IPEndPoint(localaddress,49155); // 创建Socket对象,使用IPv4地址,数据通信类型为数据流,传输控制协议TCP协议. Socket socket = new Socket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp); //将Socket绑定到断点上 socket.Bind(endpoint); // 设置连接队列的长度 socket.Listen(10); while (true) { Console.WriteLine("Wait an connect Request..."); // 开始监听,这个方法会堵塞线程的执行,直到接受到一个客户端的连接请求 Socket clientsocket =socket.Accept(); // 输出客户端的地址 Console.WriteLine("Client Address is: {0}", clientsocket.RemoteEndPoint); // 把客户端的请求数据读入保存到一个数组中 byte[] buffer =new byte[2048]; int receivelength = clientsocket.Receive(buffer, 2048, SocketFlags.None); string requeststring = Encoding.UTF8.GetString(buffer, 0, receivelength); // 在服务器端输出请求的消息 Console.WriteLine(requeststring); // 服务器端做出相应内容 // 响应的状态行 string statusLine ="HTTP/1.1 200 OK\r\n"; byte[] responseStatusLineBytes = Encoding.UTF8.GetBytes(statusLine); string responseBody = "<html><head><title>Default Page</title></head><body><p style='font:bold;font-size:24pt'>Welcome you</p></body></html>"; string responseHeader = string.Format( "Content-Type: text/html; charset=UTf-8\r\nContent-Length: {0}\r\n",responseBody.Length); byte[] responseHeaderBytes = Encoding.UTF8.GetBytes(responseHeader); byte[] responseBodyBytes = Encoding.UTF8.GetBytes(responseBody); // 向客户端发送状态行 clientsocket.Send(responseStatusLineBytes); // 向客户端发送回应头信息 clientsocket.Send(responseHeaderBytes); // 发送头部和内容的空行 clientsocket.Send(new byte[] { 13, 10 }); // 想客户端发送主体部分 clientsocket.Send(responseBodyBytes); // 断开连接 clientsocket.Close(); Console.ReadKey(); break; } // 关闭服务器 socket.Close(); } private static void TcpServer() { // 获得本机的Ip地址,即127.0.0.1 IPAddress localaddress = IPAddress.Loopback; // 创建可以访问的断点,49155表示端口号,如果这里设置为0,表示使用一个由系统分配的空闲的端口号 IPEndPoint endpoint = new IPEndPoint(localaddress, 49155); // 创建Tcp 监听器 TcpListener tcpListener = new TcpListener(endpoint); // 启动监听 tcpListener.Start(); Console.WriteLine("Wait an connect Request..."); while (true) { // 等待客户连接 TcpClient client = tcpListener.AcceptTcpClient(); if (client.Connected == true) { // 输出已经建立连接 Console.WriteLine("Created connection"); } // 获得一个网络流对象 // 该网络流对象封装了Socket的输入和输出操作 // 此时通过对网络流对象进行写入来返回响应消息 // 通过对网络流对象进行读取来获得请求消息 NetworkStream netstream = client.GetStream(); // 把客户端的请求数据读入保存到一个数组中 byte[] buffer = new byte[2048]; int receivelength = netstream.Read(buffer, 0, 2048); string requeststring = Encoding.UTF8.GetString(buffer, 0, receivelength); // 在服务器端输出请求的消息 Console.WriteLine(requeststring); // 服务器端做出相应内容 // 响应的状态行 string statusLine = "HTTP/1.1 200 OK\r\n"; byte[] responseStatusLineBytes = Encoding.UTF8.GetBytes(statusLine); string responseBody = "<html><head><title>Default Page</title></head><body><p style='font:bold;font-size:24pt'>Welcome you</p></body></html>"; string responseHeader = string.Format( "Content-Type: text/html; charset=UTf-8\r\nContent-Length: {0}\r\n", responseBody.Length); byte[] responseHeaderBytes = Encoding.UTF8.GetBytes(responseHeader); byte[] responseBodyBytes = Encoding.UTF8.GetBytes(responseBody); // 写入状态行信息 netstream.Write(responseStatusLineBytes, 0, responseStatusLineBytes.Length); // 写入回应的头部 netstream.Write(responseHeaderBytes, 0, responseHeaderBytes.Length); // 写入回应头部和内容之间的空行 netstream.Write(new byte[] { 13, 10 }, 0, 2); // 写入回应的内容 netstream.Write(responseBodyBytes, 0, responseBodyBytes.Length); // 关闭与客户端的连接 client.Close(); } // 关闭服务器 //tcpListener.Stop(); } private static void GetClientMsg() { TcpListener listener = new TcpListener(IPAddress.Any, 1300); listener.Start(); while (true) { Console.WriteLine("start listen"); TcpClient client = listener.AcceptTcpClient(); NetworkStream stream = client.GetStream(); byte[] buffer = new byte[128]; stream.Read(buffer, 0, buffer.Length); string text = System.Text.Encoding.UTF8.GetString(buffer); Console.WriteLine(text); client.Close(); } } }
2、基于socket的局域网聊天程序
界面如下:
本地会启动一个socket来监听访问,点击按钮会启用一个socket来发送消息,为发送消息的socket端口占用,每次会检查是否端口占用。
public partial class SocketChatForm : Form { private int serverPort = 1347; Thread listenThread = null; Thread sendThread = null; Socket acceptClient = null; private IPAddress TargetIP { get { string ip = "127.0.0.1"; if (!string.IsNullOrEmpty(tbIP.Text.Trim())) { ip = tbIP.Text.Trim(); } return IPAddress.Parse(ip); } } public SocketChatForm() { InitializeComponent(); listenThread = new Thread(new ThreadStart(ReceiveMsg)); listenThread.Start(); } private void btnSend_Click(object sender, EventArgs e) { sendThread = new Thread(new ThreadStart(SendMsg)); sendThread.Start(); } private void SendMsg() { Socket socketClient = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); int clientPort = new Random().Next(10000); while (PortInUse(clientPort)) { clientPort = new Random().Next(10000); } IPEndPoint localEndpoint = new IPEndPoint(IPAddress.Loopback, clientPort); socketClient.Bind(localEndpoint); IPEndPoint remoteEndpoint = new IPEndPoint(TargetIP, serverPort); string text = tbMsg.Text.Trim(); if (string.IsNullOrEmpty(text)) { return; } byte[] buffer = System.Text.Encoding.UTF8.GetBytes(text); try { socketClient.Connect(remoteEndpoint); } catch { MessageBox.Show("无法连接到目标地址"); return; } socketClient.Send(buffer); socketClient.Close(); this.Invoke(new MsgHandler(SetText), string.Empty); sendThread.Abort(); } private void ReceiveMsg() { Socket socketServer = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); IPEndPoint endpoint = new IPEndPoint(IPAddress.Loopback, serverPort); socketServer.Bind(endpoint); socketServer.Listen(10); while (true) { acceptClient = socketServer.Accept(); byte[] buffer = new byte[256]; int len = acceptClient.Receive(buffer); string text = System.Text.Encoding.UTF8.GetString(buffer); this.Invoke(new MsgHandler(AddListView), text); acceptClient.Close(); acceptClient = null; } } private delegate void MsgHandler(string msg); private void AddListView(string msg) { listBox1.Items.Add(msg); } private void SetText(string msg) { tbMsg.Text = msg; } /// <summary> /// 检查端口号是否被占用 /// </summary> /// <param name="port"></param> /// <returns></returns> public static bool PortInUse(int port) { bool inUse = false; IPGlobalProperties ipProperties = IPGlobalProperties.GetIPGlobalProperties(); IPEndPoint[] ipEndPoints = ipProperties.GetActiveTcpListeners(); foreach (IPEndPoint endPoint in ipEndPoints) { if (endPoint.Port == port) { inUse = true; break; } } ipProperties = null; return inUse; } }
当然也可以用TcpClient和TcpListener来实现。或者使用无连接的UDP来实现。
3、关闭窗口时有些资源没有释放导致进程一直挂起。可以在Dispose方法中加入System.Environment.Exit(0);来退出进程