前一章节我提到了在Windows,LINUIX内核已经有了完整的TCP/IP实现,只要会调用专用接口函数: Socket和TLI(传输层接口)就足够了,正好我最近在了解C#,所以便通过Socket实现简单的客户端/服务器模型,程序本身并不难,不过理解了之后对于认知TCP/IP有着良好的促进作用。
想要实现Socket通讯,具体实现参考标准的流程,如下图:
了解了上图,那么就可以开始C#的编程了(窗体设计等参考源码,我主要讲解核心代码):
客户端:
客户端的实现比较简单
1.建立tcp连接(等同于socket 和 connect),处理连接失败状态
2.对于建立成功的连接,发送数据,并等待服务器返回
3.接收数据,输出到编辑框
4.关闭连接
private void button1_Click(object sender, EventArgs e) { try { string s_ipaddress0 = textBox1.Text; string s_ipaddress1 = textBox2.Text; string s_ipaddress2 = textBox3.Text; string s_ipaddress3 = textBox4.Text; string s_port = textBox5.Text; //限定port的合法性 bool isPort; int port; isPort = Int32.TryParse(s_port, out port); if (!(isPort && port >= 0 && port <= 65536)) { OutToClient("Port is Invalid!"); return; } //限定ip地址的合法性 string host = s_ipaddress0 + "." + s_ipaddress1 + "." + s_ipaddress2 + "." + s_ipaddress3; if (!IsIpAdress(host)) { OutToClient("IpAdress is invaild!"); return; } IPAddress ip = IPAddress.Parse(host); IPEndPoint ipe = new IPEndPoint(ip, port); //Ip端口绑定 如192.168.1.48:80 //发送框不能为空, 不然会导致GetBytes出错 if (textBox6.Text == "") { OutToClient("Send Text is empty!"); return; } OutToClient("Conneting..."); int timeout = 1000; //tcpClient连接到指定端口,并处理超时 TcpClient NetworkClient = TimeOutSocket.Connect(ipe, timeout); NetworkStream ntwStream = NetworkClient.GetStream(); if (!ntwStream.CanWrite) { OutToClient("Data can not be write!"); return; } //向绑定地址端口发送数据 OutToClient("Client send:" + textBox6.Text); string sendStr = textBox6.Text; byte[] by_send = Encoding.ASCII.GetBytes(sendStr); ntwStream.Write(by_send, 0, by_send.Length); //等待服务器端返回数据 string recvStr = ""; byte[] recvBytes = new byte[4096]; int bytes = ntwStream.Read(recvBytes, 0, recvBytes.Length); //将接收到数据转发输出到Client编辑框 recvStr += Encoding.ASCII.GetString(recvBytes, 0, bytes); OutToClient(recvStr); //关闭连接, 一次发送完成 ntwStream.Close(); NetworkClient.Close(); OutToClient("Conneting Close!\r\n"); } catch (ArgumentNullException ii) { OutToClient("ArgumentNullException: "+ ii); } catch (SocketException ii) { OutToClient("Socket failed! "); } catch (Exception ii) { OutToClient("Conneting faild!" + ii); } }
服务器内的代码涉及到的知识多一些(因为初学C#,没有理解委托,所以用线程方式处理)
1.通过按键1开辟监听线程,用于接收
2.监听线程创建Socket套接字,绑定到指定端口并监听
3.监听线程堵塞在等带连接建立
4.连接建立后监听线程读取客户端数据并回送给客户端处理后数据,然后循环堵塞在连接建立
5.通过按键2删除Socket套接字触发异常,结束线程(不知道怎么处理,只能用比较low的方法)
按照上述的流程,程序如下:
//新建线程 开始监听 private void button1_Click(object sender, EventArgs e) { try { isConnectExit = false; button1.Enabled = false; button2.Enabled = true; Thread Listen_thread = new Thread(ListenClientConnect); Listen_thread.IsBackground = true; Listen_thread.Start(); } catch (Exception ii) { OutToServer("Connet faild!" + ii); } }
//监听线程 主要处理数据接收发送 private void ListenClientConnect(object obj) { string s_ipaddress0 = textBox1.Text; string s_ipaddress1 = textBox2.Text; string s_ipaddress2 = textBox3.Text; string s_ipaddress3 = textBox4.Text; string s_port = textBox5.Text; //限定port的合法性 bool isPort; int port; isPort = Int32.TryParse(s_port, out port); if (!(isPort && port >= 0 && port <= 65536)) { OutToServer("Port is Invalid!"); return; } //限定ip地址的合法性 string host = s_ipaddress0 + "." + s_ipaddress1 + "." + s_ipaddress2 + "." + s_ipaddress3; if (!IsIpAdress(host)) { OutToServer("IpAdress is invaild!"); return; } IPAddress ip = IPAddress.Parse(host); IPEndPoint ipe = new IPEndPoint(ip, port); //新建socket通讯 绑定指定IP+Port 并监听 server_socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); server_socket.Bind(ipe); server_socket.Listen(10); OutToServer("wait for connect..."); while (isConnectExit == false) { Socket CurrentSocket; try { //等待连接 完成三次握手 CurrentSocket = server_socket.Accept(); if(isConnectExit == true) { CurrentSocket.Close(); // 关闭Socket server_socket.Close(); break; } OutToServer("Get a Connect!"); ServerProcess(CurrentSocket); } catch { OutToServer("Connet exti!"); } } }
//断开连接 private void button2_Click(object sender, EventArgs e) { isConnectExit = true; button2.Enabled = false; button1.Enabled = true; if (server_socket != null) { server_socket.Close(); } }
如此就完成了简单的C/S服务器功能。
实际测试界面如下:
具体源码参考:http://files.cnblogs.com/files/zc110747/socket.7z
时间: 2024-07-31 13:09:55