• 基于winsocket的框体Server和Client


       前面学了一点Winsock的知识,会编写简单的Server和Client,现在就想通过VS2008编写框体的Server和Client,而不是在控制台上的操作了,毕竟学编程就是要多加练习,在实践中发现不懂的地方,然后解决,然后再发现……

       当然,作为一个刚接触Winsock的新手,大部分知识都来自于网上的资料,包括接下来的代码也是借鉴。。。

    1. 第一步利用VS2008创建一个Windows窗体应用程序chatServer(过程略);
    2. 设计你的窗体,简单的设计了一个窗体

      注意,每一个组件都需要有唯一的Name,在设置好组件的属性后,可以双击这个组件,则会自动生成对应的动作函数;
    3. 在Form1.h中写入如下代码,注意里面很多的函数时根据组件Name来命名的,所以copy时需要注意这一点;
        1         #pragma once
        2 
        3 
        4 namespace chatServer {
        5 
        6     using namespace System;   
        7     using namespace System::ComponentModel;  
        8     using namespace System::Collections;  
        9     using namespace System::Windows::Forms;  
       10     using namespace System::Data;  
       11     using namespace System::Drawing;  
       12     using namespace System::Threading;  
       13     using namespace System::Text;  
       14     using namespace System::Net;   
       15     using namespace System::Net::Sockets;  
       16     using namespace System::IO;
       17     
       18     /// <summary>
       19     /// Form1 摘要
       20     ///
       21     /// 警告: 如果更改此类的名称,则需要更改
       22     ///          与此类所依赖的所有 .resx 文件关联的托管资源编译器工具的
       23     ///          “资源文件名”属性。否则,
       24     ///          设计器将不能与此窗体的关联
       25     ///          本地化资源正确交互。
       26     /// </summary>
       27     public ref class Form1 : public System::Windows::Forms::Form
       28     {
       29     Socket^ mySocket;
       30     Socket^ tempSocket;
       31     Thread^ myThread;
       32     int port;
       33     String^ host;
       34 
       35     public:
       36         Form1(void)
       37         {
       38             InitializeComponent();
       39             //
       40             //TODO: 在此处添加构造函数代码
       41             //
       42         }
       43 
       44     protected:
       45         /// <summary>
       46         /// 清理所有正在使用的资源。
       47         /// </summary>
       48         ~Form1()
       49         {
       50             if (components)
       51             {
       52                 delete components;
       53             }
       54         }
       55     private: System::Windows::Forms::TextBox^  IPBox;
       56     private: System::Windows::Forms::Label^  IP;
       57     private: System::Windows::Forms::TextBox^  ShowBox;
       58     private: System::Windows::Forms::TextBox^  InputBox;
       59     private: System::Windows::Forms::Label^  InputLabel;
       60     private: System::Windows::Forms::Button^  SendButton;
       61     private: System::Windows::Forms::Button^  ExitButton;
       62     public : String^ m_ShowText;
       63     public : String^ m_IPShowText;
       64 
       65 
       66 
       67 
       68 
       69 
       70     protected: 
       71 
       72 
       73     private:
       74         /// <summary>
       75         /// 必需的设计器变量。
       76         /// </summary>
       77         System::ComponentModel::Container ^components;
       78 
       79 #pragma region Windows Form Designer generated code
       80         /// <summary>
       81         /// 设计器支持所需的方法 - 不要
       82         /// 使用代码编辑器修改此方法的内容。
       83         /// </summary>
       84         void InitializeComponent(void)
       85         {
       86             this->IPBox = (gcnew System::Windows::Forms::TextBox());
       87             this->IP = (gcnew System::Windows::Forms::Label());
       88             this->ShowBox = (gcnew System::Windows::Forms::TextBox());
       89             this->InputBox = (gcnew System::Windows::Forms::TextBox());
       90             this->InputLabel = (gcnew System::Windows::Forms::Label());
       91             this->SendButton = (gcnew System::Windows::Forms::Button());
       92             this->ExitButton = (gcnew System::Windows::Forms::Button());
       93             this->SuspendLayout();
       94             // 
       95             // IPBox
       96             // 
       97             this->IPBox->Location = System::Drawing::Point(12, 21);
       98             this->IPBox->Name = L"IPBox";
       99             this->IPBox->Size = System::Drawing::Size(181, 21);
      100             this->IPBox->TabIndex = 0;
      101             this->IPBox->TextChanged += gcnew System::EventHandler(this, &Form1::IPBox_TextChanged);
      102             // 
      103             // IP
      104             // 
      105             this->IP->AutoSize = true;
      106             this->IP->BackColor = System::Drawing::SystemColors::InactiveCaption;
      107             this->IP->Font = (gcnew System::Drawing::Font(L"宋体", 21.75F, System::Drawing::FontStyle::Regular, System::Drawing::GraphicsUnit::Point, 
      108                 static_cast<System::Byte>(134)));
      109             this->IP->Location = System::Drawing::Point(199, 13);
      110             this->IP->Name = L"IP";
      111             this->IP->Size = System::Drawing::Size(178, 29);
      112             this->IP->TabIndex = 1;
      113             this->IP->Text = L"IP and Port";
      114             this->IP->Click += gcnew System::EventHandler(this, &Form1::IP_Click);
      115             // 
      116             // ShowBox
      117             // 
      118             this->ShowBox->Location = System::Drawing::Point(12, 48);
      119             this->ShowBox->Multiline = true;
      120             this->ShowBox->Name = L"ShowBox";
      121             this->ShowBox->ScrollBars = System::Windows::Forms::ScrollBars::Vertical;
      122             this->ShowBox->Size = System::Drawing::Size(365, 224);
      123             this->ShowBox->TabIndex = 2;
      124             this->ShowBox->TextChanged += gcnew System::EventHandler(this, &Form1::ShowBox_TextChanged);
      125             // 
      126             // InputBox
      127             // 
      128             this->InputBox->Location = System::Drawing::Point(12, 301);
      129             this->InputBox->Name = L"InputBox";
      130             this->InputBox->ScrollBars = System::Windows::Forms::ScrollBars::Vertical;
      131             this->InputBox->Size = System::Drawing::Size(364, 21);
      132             this->InputBox->TabIndex = 3;
      133             this->InputBox->TextChanged += gcnew System::EventHandler(this, &Form1::InputBox_TextChanged);
      134             // 
      135             // InputLabel
      136             // 
      137             this->InputLabel->AutoSize = true;
      138             this->InputLabel->Location = System::Drawing::Point(12, 279);
      139             this->InputLabel->Name = L"InputLabel";
      140             this->InputLabel->Size = System::Drawing::Size(113, 12);
      141             this->InputLabel->TabIndex = 4;
      142             this->InputLabel->Text = L"输入你要发送的信息";
      143             this->InputLabel->Click += gcnew System::EventHandler(this, &Form1::InputLabel_Click);
      144             // 
      145             // SendButton
      146             // 
      147             this->SendButton->Location = System::Drawing::Point(34, 329);
      148             this->SendButton->Name = L"SendButton";
      149             this->SendButton->Size = System::Drawing::Size(75, 23);
      150             this->SendButton->TabIndex = 5;
      151             this->SendButton->Text = L"发送";
      152             this->SendButton->UseVisualStyleBackColor = true;
      153             this->SendButton->Click += gcnew System::EventHandler(this, &Form1::SendButton_Click);
      154             // 
      155             // ExitButton
      156             // 
      157             this->ExitButton->Location = System::Drawing::Point(296, 329);
      158             this->ExitButton->Name = L"ExitButton";
      159             this->ExitButton->Size = System::Drawing::Size(75, 23);
      160             this->ExitButton->TabIndex = 6;
      161             this->ExitButton->Text = L"退出";
      162             this->ExitButton->UseVisualStyleBackColor = true;
      163             this->ExitButton->Click += gcnew System::EventHandler(this, &Form1::ExitButton_Click);
      164             // 
      165             // Form1
      166             // 
      167             this->AutoScaleDimensions = System::Drawing::SizeF(6, 12);
      168             this->AutoScaleMode = System::Windows::Forms::AutoScaleMode::Font;
      169             this->ClientSize = System::Drawing::Size(425, 367);
      170             this->Controls->Add(this->ExitButton);
      171             this->Controls->Add(this->SendButton);
      172             this->Controls->Add(this->InputLabel);
      173             this->Controls->Add(this->InputBox);
      174             this->Controls->Add(this->ShowBox);
      175             this->Controls->Add(this->IP);
      176             this->Controls->Add(this->IPBox);
      177             this->Name = L"Form1";
      178             this->Text = L"聊天---服务端";
      179             this->Load += gcnew System::EventHandler(this, &Form1::Form1_Load);
      180             this->ResumeLayout(false);
      181             this->PerformLayout();
      182 
      183         }
      184 #pragma endregion
      185         delegate void UpdateShowBox_Invoke();
      186         void UpdateShowBox()
      187         {
      188             ShowBox->AppendText(m_ShowText);//在后面追加显示新的内容
      189         }
      190 
      191         delegate void UpdateIPShowBox_Invoke();
      192         void UpdateIPShowBox()
      193         {
      194             IPBox->AppendText(m_IPShowText);
      195         }
      196 
      197         void DoWork()
      198         {        
      199             port = 2020;//设置端口号     
      200             host = "1.1.1.1";
      201             //设置服务器地址,这里需要你本机的ip        
      202             IPAddress^ ip = IPAddress::Parse(host);
      203             
      204             IPEndPoint^ ipe = gcnew IPEndPoint(ip,port);
      205             mySocket = gcnew  Socket(AddressFamily::InterNetwork,SocketType::Stream,ProtocolType::Tcp);//创建一个socket类
      206             mySocket->Bind(ipe);//绑定端口
      207             m_IPShowText = host+" // "+port;
      208             this->Invoke(gcnew  UpdateIPShowBox_Invoke(this,&Form1::UpdateIPShowBox));//显示IP和端口号
      209             mySocket->Listen(0);//开始监听     
      210             tempSocket = mySocket->Accept();//为新建连接创建新的Socket    
      211             //连接上后进行死循环,避免断开连接    
      212             
      213             while(1){         
      214                 try{       
      215                     String^ recvStr = "";       
      216                     array<Byte>^ recvBytes = gcnew array<Byte>(1024);      
      217                     int bytes;   
      218                     bytes = tempSocket->Receive(recvBytes,recvBytes->Length,SocketFlags::None); //从客户端接收信息
      219                     recvStr = Encoding::Default->GetString(recvBytes,0,bytes); //转换数据为字符串
      220                     m_ShowText = "
      "+"Client 说:"+"
      "+recvStr+"
      "; //加上换行符把客户端传来的信息显示出来
      221                     this->Invoke(gcnew UpdateShowBox_Invoke(this,&Form1::UpdateShowBox));
      222                 }
      223                 catch(EndOfStreamException^ e)     
      224                 {     
      225                 }      
      226                 catch(IOException^ e)     
      227                 {       
      228                     MessageBox::Show("I/O error");     
      229                 } 
      230             }   
      231         }
      232 
      233     private: System::Void label1_Click(System::Object^  sender, System::EventArgs^  e) {
      234              }
      235     private: System::Void Form1_Load(System::Object^  sender, System::EventArgs^  e) {
      236                  
      237                  myThread = gcnew Thread(gcnew ThreadStart(this,&Form1::DoWork));
      238                  //创建一个线程 
      239                  myThread->IsBackground = false;
      240                  myThread->Start();
      241              }
      242 private: System::Void SendButton_Click(System::Object^  sender, System::EventArgs^  e) {       
      243              String^ sendStr = InputBox->Text;    
      244              if(sendStr->Length > 0)    
      245              {    
      246                  m_ShowText = "
      "+"我说:"+"
      "+sendStr+"
      ";
      247                  //加上换行符    
      248                  this->Invoke(gcnew  UpdateShowBox_Invoke(this,&Form1::UpdateShowBox));
      249                  //本窗口显示发出去的内容    
      250                  array<Byte>^ bs = Encoding::Default->GetBytes(sendStr); 
      251                  //将字符串转为二进制,支持中英文传输     
      252                  tempSocket->Send(bs,bs->Length,SocketFlags::None); 
      253                  //把当前的聊天内容发送给客户端    
      254                  InputBox->Text = "";    
      255              }
      256          }
      257 private: System::Void ExitButton_Click(System::Object^  sender, System::EventArgs^  e) {
      258              tempSocket->Close();
      259              mySocket->Close();
      260              myThread->Abort();
      261              Application::Exit();
      262          }
      263 private: System::Void IP_Click(System::Object^  sender, System::EventArgs^  e) {
      264          }
      265 private: System::Void InputLabel_Click(System::Object^  sender, System::EventArgs^  e) {
      266          }
      267 private: System::Void ShowBox_TextChanged(System::Object^  sender, System::EventArgs^  e) {
      268          }
      269 private: System::Void IPBox_TextChanged(System::Object^  sender, System::EventArgs^  e) {
      270          }
      271 private: System::Void InputBox_TextChanged(System::Object^  sender, System::EventArgs^  e) {
      272          }
      273 };
      274 }
    4. 在chatServer中加入这一行代码:using namespace System::Threading;到此Server就基本完成了。。
    5. 仿照这样的方法完成Client端
    6. chatClient过程中Form1.h的代码
        1 #pragma once
        2 
        3 
        4 namespace chatClient {
        5 
        6     using namespace System;   
        7     using namespace System::ComponentModel;  
        8     using namespace System::Collections;  
        9     using namespace System::Windows::Forms;  
       10     using namespace System::Data;  
       11     using namespace System::Drawing;  
       12     using namespace System::Threading;  
       13     using namespace System::Text;  
       14     using namespace System::Net;   
       15     using namespace System::Net::Sockets;  
       16     using namespace System::IO;
       17 
       18     /// <summary>
       19     /// Form1 摘要
       20     ///
       21     /// 警告: 如果更改此类的名称,则需要更改
       22     ///          与此类所依赖的所有 .resx 文件关联的托管资源编译器工具的
       23     ///          “资源文件名”属性。否则,
       24     ///          设计器将不能与此窗体的关联
       25     ///          本地化资源正确交互。
       26     /// </summary>
       27     public ref class Form1 : public System::Windows::Forms::Form
       28     {
       29         Socket^ mySocket;
       30         Socket^ tempSocket;
       31         Thread^ myThread;
       32         int port;
       33         String^ host;
       34 
       35     public:
       36         Form1(void)
       37         {
       38             InitializeComponent();
       39             //
       40             //TODO: 在此处添加构造函数代码
       41             //
       42         }
       43 
       44     protected:
       45         /// <summary>
       46         /// 清理所有正在使用的资源。
       47         /// </summary>
       48         ~Form1()
       49         {
       50             if (components)
       51             {
       52                 delete components;
       53             }
       54         }
       55     private: System::Windows::Forms::TextBox^  IPShowBox;
       56     protected: 
       57 
       58     private: System::Windows::Forms::TextBox^  showBox;
       59     protected: 
       60 
       61     private: System::Windows::Forms::Label^  label1;
       62     private: System::Windows::Forms::Label^  InputLabel;
       63     private: System::Windows::Forms::TextBox^  InputBox;
       64     private: System::Windows::Forms::Button^  SendButton;
       65     private: System::Windows::Forms::Button^  exitButton;
       66     public : String^ m_ShowText;
       67     public : String^ m_IPShowText;
       68 
       69 
       70 
       71 
       72 
       73     private:
       74         /// <summary>
       75         /// 必需的设计器变量。
       76         /// </summary>
       77         System::ComponentModel::Container ^components;
       78 
       79 #pragma region Windows Form Designer generated code
       80         /// <summary>
       81         /// 设计器支持所需的方法 - 不要
       82         /// 使用代码编辑器修改此方法的内容。
       83         /// </summary>
       84         void InitializeComponent(void)
       85         {
       86             this->IPShowBox = (gcnew System::Windows::Forms::TextBox());
       87             this->showBox = (gcnew System::Windows::Forms::TextBox());
       88             this->label1 = (gcnew System::Windows::Forms::Label());
       89             this->InputLabel = (gcnew System::Windows::Forms::Label());
       90             this->InputBox = (gcnew System::Windows::Forms::TextBox());
       91             this->SendButton = (gcnew System::Windows::Forms::Button());
       92             this->exitButton = (gcnew System::Windows::Forms::Button());
       93             this->SuspendLayout();
       94             // 
       95             // IPShowBox
       96             // 
       97             this->IPShowBox->Location = System::Drawing::Point(32, 23);
       98             this->IPShowBox->Multiline = true;
       99             this->IPShowBox->Name = L"IPShowBox";
      100             this->IPShowBox->Size = System::Drawing::Size(226, 30);
      101             this->IPShowBox->TabIndex = 0;
      102             this->IPShowBox->TextChanged += gcnew System::EventHandler(this, &Form1::IPShowBox_TextChanged);
      103             // 
      104             // showBox
      105             // 
      106             this->showBox->Location = System::Drawing::Point(32, 59);
      107             this->showBox->Multiline = true;
      108             this->showBox->Name = L"showBox";
      109             this->showBox->ScrollBars = System::Windows::Forms::ScrollBars::Vertical;
      110             this->showBox->Size = System::Drawing::Size(425, 208);
      111             this->showBox->TabIndex = 1;
      112             this->showBox->TextChanged += gcnew System::EventHandler(this, &Form1::showBox_TextChanged);
      113             // 
      114             // label1
      115             // 
      116             this->label1->AutoSize = true;
      117             this->label1->Font = (gcnew System::Drawing::Font(L"宋体", 18, System::Drawing::FontStyle::Regular, System::Drawing::GraphicsUnit::Point, 
      118                 static_cast<System::Byte>(134)));
      119             this->label1->Location = System::Drawing::Point(264, 23);
      120             this->label1->Name = L"label1";
      121             this->label1->Size = System::Drawing::Size(142, 24);
      122             this->label1->TabIndex = 2;
      123             this->label1->Text = L"IP and Port
      ";
      124             // 
      125             // InputLabel
      126             // 
      127             this->InputLabel->AutoSize = true;
      128             this->InputLabel->Location = System::Drawing::Point(32, 274);
      129             this->InputLabel->Name = L"InputLabel";
      130             this->InputLabel->Size = System::Drawing::Size(53, 12);
      131             this->InputLabel->TabIndex = 3;
      132             this->InputLabel->Text = L"输入信息";
      133             // 
      134             // InputBox
      135             // 
      136             this->InputBox->Location = System::Drawing::Point(34, 290);
      137             this->InputBox->Name = L"InputBox";
      138             this->InputBox->Size = System::Drawing::Size(302, 21);
      139             this->InputBox->TabIndex = 4;
      140             this->InputBox->TextChanged += gcnew System::EventHandler(this, &Form1::InputBox_TextChanged);
      141             // 
      142             // SendButton
      143             // 
      144             this->SendButton->Location = System::Drawing::Point(43, 317);
      145             this->SendButton->Name = L"SendButton";
      146             this->SendButton->Size = System::Drawing::Size(75, 23);
      147             this->SendButton->TabIndex = 5;
      148             this->SendButton->Text = L"发送";
      149             this->SendButton->UseVisualStyleBackColor = true;
      150             this->SendButton->Click += gcnew System::EventHandler(this, &Form1::SendButton_Click);
      151             // 
      152             // exitButton
      153             // 
      154             this->exitButton->Location = System::Drawing::Point(318, 317);
      155             this->exitButton->Name = L"exitButton";
      156             this->exitButton->Size = System::Drawing::Size(75, 23);
      157             this->exitButton->TabIndex = 6;
      158             this->exitButton->Text = L"退出";
      159             this->exitButton->UseVisualStyleBackColor = true;
      160             this->exitButton->Click += gcnew System::EventHandler(this, &Form1::exitButton_Click);
      161             // 
      162             // Form1
      163             // 
      164             this->AutoScaleDimensions = System::Drawing::SizeF(6, 12);
      165             this->AutoScaleMode = System::Windows::Forms::AutoScaleMode::Font;
      166             this->ClientSize = System::Drawing::Size(469, 350);
      167             this->Controls->Add(this->exitButton);
      168             this->Controls->Add(this->SendButton);
      169             this->Controls->Add(this->InputBox);
      170             this->Controls->Add(this->InputLabel);
      171             this->Controls->Add(this->label1);
      172             this->Controls->Add(this->showBox);
      173             this->Controls->Add(this->IPShowBox);
      174             this->Name = L"Form1";
      175             this->Text = L"聊天--客户端";
      176             this->Load += gcnew System::EventHandler(this, &Form1::Form1_Load);
      177             this->ResumeLayout(false);
      178             this->PerformLayout();
      179 
      180         }
      181 #pragma endregion
      182 
      183         delegate void UpdateShowBox_Invoke();
      184         void UpdateShowBox()
      185         {
      186             showBox->AppendText(m_ShowText);//在后面追加显示新的内容
      187         }
      188 
      189         delegate void UpdateIPShowBox_Invoke();
      190         void UpdateIPShowBox()
      191         {
      192             IPShowBox->AppendText(m_IPShowText);
      193         }
      194 
      195         void DoWork()
      196         {        
      197             port = 2020;//设置端口号     
      198             host = "1.1.1.1";//设置服务器地址
      199             IPAddress^ ip = IPAddress::Parse(host);
      200             IPEndPoint^ ipe = gcnew IPEndPoint(ip,port);
      201             mySocket = gcnew  Socket(AddressFamily::InterNetwork,SocketType::Stream,ProtocolType::Tcp);//创建一个socket类
      202             mySocket->Connect(ipe);
      203             m_IPShowText = host+" // "+port;
      204             this->Invoke(gcnew  UpdateIPShowBox_Invoke(this,&Form1::UpdateIPShowBox));//显示IP和端口号    
      205             //连接上后进行死循环,避免断开连接    
      206             while(1){         
      207                 try{       
      208                     String^ recvStr = "";       
      209                     array<Byte>^ recvBytes = gcnew array<Byte>(1024);      
      210                     int bytes;   
      211                     bytes = mySocket->Receive(recvBytes,recvBytes->Length,SocketFlags::None); //从客户端接收信息
      212                     recvStr = Encoding::Default->GetString(recvBytes,0,bytes); //转换数据为字符串
      213                     m_ShowText = "
      "+"Server 说:"+"
      "+recvStr+"
      "; //加上换行符把客户端传来的信息显示出来
      214                     this->Invoke(gcnew UpdateShowBox_Invoke(this,&Form1::UpdateShowBox));
      215                 }
      216                 catch(EndOfStreamException^ e)     
      217                 {     
      218                 }      
      219                 catch(IOException^ e)     
      220                 {       
      221                     MessageBox::Show("I/O error");     
      222                 } 
      223             }   
      224         }
      225 
      226 
      227 private: System::Void exitButton_Click(System::Object^  sender, System::EventArgs^  e) {
      228              mySocket->Close();
      229              myThread->Abort();
      230              Application::Exit();
      231          }
      232 private: System::Void SendButton_Click(System::Object^  sender, System::EventArgs^  e) {
      233              String^ sendStr = InputBox->Text;    
      234              if(sendStr->Length > 0)    
      235              {    
      236                  m_ShowText = "
      "+"我说:"+"
      "+sendStr+"
      ";
      237                  //加上换行符    
      238                  this->Invoke(gcnew  UpdateShowBox_Invoke(this,&Form1::UpdateShowBox));
      239                  //本窗口显示发出去的内容    
      240                  array<Byte>^ bs = Encoding::Default->GetBytes(sendStr); 
      241                  //将字符串转为二进制,支持中英文传输     
      242                  mySocket->Send(bs,bs->Length,SocketFlags::None); 
      243                  //把当前的聊天内容发送给客户端    
      244                  InputBox->Text = "";    
      245              }
      246          }
      247 private: System::Void InputBox_TextChanged(System::Object^  sender, System::EventArgs^  e) {
      248          }
      249 private: System::Void showBox_TextChanged(System::Object^  sender, System::EventArgs^  e) {
      250          }
      251 private: System::Void IPShowBox_TextChanged(System::Object^  sender, System::EventArgs^  e) {
      252          }
      253 private: System::Void Form1_Load(System::Object^  sender, System::EventArgs^  e) {
      254              myThread = gcnew Thread(gcnew ThreadStart(this,&Form1::DoWork));
      255              //创建一个线程
      256              myThread->IsBackground = true;
      257              myThread->Start();
      258          }
      259 };
      260 }
    7. 同样需要在chatClient中加入using namespace System::Threading;
    8. 接下来执行,先打开Server,在打开Client
    9. 结果是:
  • 相关阅读:
    查全球服务器的网站
    linux passwd文件中位置所对应的信息
    linux目录清单
    mysql自动添加编号
    mysql优化学习
    maven的基本使用2
    SpringBoot的基本使用
    Mybatis的缓存
    部分属性及方法的浏览器兼容问题
    Mybatis的sql mapper映射文件详解
  • 原文地址:https://www.cnblogs.com/LCCRNblog/p/3851790.html
Copyright © 2020-2023  润新知