前面学了一点Winsock的知识,会编写简单的Server和Client,现在就想通过VS2008编写框体的Server和Client,而不是在控制台上的操作了,毕竟学编程就是要多加练习,在实践中发现不懂的地方,然后解决,然后再发现……
当然,作为一个刚接触Winsock的新手,大部分知识都来自于网上的资料,包括接下来的代码也是借鉴。。。
- 第一步利用VS2008创建一个Windows窗体应用程序chatServer(过程略);
- 设计你的窗体,简单的设计了一个窗体
注意,每一个组件都需要有唯一的Name,在设置好组件的属性后,可以双击这个组件,则会自动生成对应的动作函数; - 在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 = "\r\n"+"Client 说:"+"\r\n"+recvStr+"\r\n"; //加上换行符把客户端传来的信息显示出来 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 = "\r\n"+"我说:"+"\r\n"+sendStr+"\r\n"; 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 }
- 在chatServer中加入这一行代码:using namespace System::Threading;到此Server就基本完成了。。
- 仿照这样的方法完成Client端
- 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\r\n"; 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 = "\r\n"+"Server 说:"+"\r\n"+recvStr+"\r\n"; //加上换行符把客户端传来的信息显示出来 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 = "\r\n"+"我说:"+"\r\n"+sendStr+"\r\n"; 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 }
- 同样需要在chatClient中加入using namespace System::Threading;
- 接下来执行,先打开Server,在打开Client
- 结果是: