① 如何實現客戶端與伺服器的交互
C/S模式和B/S各有其有點也各有其缺點,B/S模式在開發中需要考慮數據如何從客戶端提交到伺服器端,數據又如何返回到客戶端,這些是B/S模式所特有的,在去年之前,開發B/S模式的程序,我都是利用form來交互數據,當我看到XML之後,發現XML是個好冬冬,有很多優點,有好的東西當然不能獨享啦,想當年為了實現XML交互數據,幾乎把網路翻了個遍。咚,一塊磚頭上來了。呵呵,廢話少說,下面我們就進入正題。
B/S模式分為伺服器端和客戶端,客戶端接受用戶的請求,客戶端向應用服務提出請求,應用服務從資料庫服務中獲得數據,應用服務將數據進行計算並將結果提交給客戶端,客戶端將結果呈現給用戶。這樣,我們就看到了數據從客戶到伺服器,經過伺服器的處理再返回到客戶端,由客戶端軟體(如IE)顯示結果。
(以ASP教本語言為例,其它的語言一樣哈。)
1.Form方式
Form方式是最基本的向伺服器提交數據的方式。
test.asp文件代碼:
<%@ Language=VBScript %>
<%
Response.Expires=-1
Response.CharSet="UTF-8"
Session.CodePage="65001"
%>
<form name="frmTest" id="frmTest" action="test.asp" method="POST">
<input name="name" id=" name" type="text" value="">
<input type="hidden" name="number" id="number" value="10">
<input type="submit" value="Submit" name="B1">
</form>
<%
dim intnumber
dim strname
if IsEmpty(Request("name")) then
strname =""
else
strname =Request("name")
end if
if IsEmpty(Request("number")) then
intnumber =0
else
intnumber =Request("number")
end if
② 網路游戲客戶端和伺服器之間數據怎麼交互的
最簡單的模式就是,
客戶端接收鍵盤,滑鼠等的消息,然後發送個伺服器。
伺服器收到這些消息後,發送給其他(指定或者所有的)客戶端
就像你在WEB聊天室聊天一樣。首先鍵盤輸入了一大堆文字。然後按下「遞交」按鈕,於是客戶端收集你填寫的那些文字內容,然後發送給伺服器。(也許裡面有些色情暴力的字眼)
伺服器在接收的這些消息後,發送給其他用戶。(伺服器可能和諧掉那些色情暴力的字眼,變成了XXOO)
網路游戲的客戶端和伺服器也是一樣的道理
客戶端紀錄所有的消息指令,一般來說,如果該消息指令可能影響到其他人的,或者需要被其他人看到,這個消息就會需要被發送到伺服器。
伺服器處理這些消息進行處理,發送給其他相關的客戶端。
直白點來說,伺服器端與客戶端分別處理哪些事情?你是老闆,你說了算。
③ C# 怎樣才能實現客戶端通過伺服器端連接資料庫伺服器
可以處理的,步驟為:
1.客戶端與伺服器連(用Socket通訊)
2.客戶端向處伺服器發送SQL語句,如搜索一個表的數據
3.伺服器接到請求,執行SQL語句返回一個DataTable
4.伺服器將這個DataTable進行序列化、並且壓縮
5.伺服器將【序列化和壓縮】後的byte[] msg數組傳給客戶端
6.客戶端收到byte[] msg數組先進行解壓縮、和反序列化為DataTable
7.再將DataTable通過DataSet和SqlDataAdapter.Update(Table)存在SQL中
下面我只給一些關鍵的代碼,我有實現過的
第一步.客戶端==》連接伺服器並通訊,主要是發送SQL給伺服器返回一個DataTable表
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Net;
using System.Net.Sockets;
using System.Xml;
using System.Xml.Serialization;
using System.IO;
using System.IO.Compression;
namespace Client
{
public partial class FormClient : Form
{
DataTable dt;
public FormClient()
{
InitializeComponent();
}
private void ClientTest(string str)
{
Socket client;
String returnData;
byte[] buf = new byte[9991024]; //此處可能有些問題
//IPAddress local = IPAddress.Parse("116.25.83.127");
IPAddress local = IPAddress.Parse("127.0.0.1");//可改為遠程IP地址
IPEndPoint iep = new IPEndPoint(local, 6060);
try
{
client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
client.Connect(iep);
}
catch (SocketException)
{
Console.WriteLine("無法連接到伺服器!");
return ;
}
//輸入exit,可以斷開與伺服器的連接
if (str == "")
{
return;
}
//發送SQL語句給伺服器
client.Send(Encoding.Unicode.GetBytes(str));
//得到實際收到的位元組總數
Int32 rec = client.Receive(buf);
Console.WriteLine(Encoding.ASCII.GetString(buf, 0, rec));
//接收伺服器返回的數據
returnData = System.Text.Encoding.Unicode.GetString(buf,0,rec);
//將returnData解壓縮後,再反序列化轉成DataTable dt = DeserializerDataTable(Decompress(returnData));
Console.WriteLine("斷開與伺服器的連接......");
client.Close();
dataGridView1.DataSource = dt;
}
//將DataTable表反序列化
private DataTable DeserializerDataTable(string pXml)
{
StringReader strReader = new StringReader(pXml);
XmlReader xmlReader = XmlReader.Create(strReader);
XmlSerializer serializer = new XmlSerializer(typeof(DataTable));
DataTable dt = serializer.Deserialize(xmlReader) as DataTable;
return dt; }
//給伺服器傳SQL語句
private void buttonSearch_Click(object sender, EventArgs e)
{
string Sql = String.Format("Select top {0} * From Part Where CorpCode_='PT'", textBox1.Text.Trim()); ;
ClientTest(Sql);
}
#region 壓縮和解壓縮
public string Compress(string str)
{
byte[] buffer = Encoding.Unicode.GetBytes(str);
MemoryStream ms = new MemoryStream();
using (GZipStream zip = new GZipStream(ms, CompressionMode.Compress, true))
{
zip.Write(buffer, 0, buffer.Length);
}
ms.Position = 0;
MemoryStream outStream = new MemoryStream();
byte[] compressed = new byte[ms.Length];
ms.Read(compressed, 0, compressed.Length);
byte[] gzBuffer = new byte[compressed.Length + 4];
System.Buffer.BlockCopy(compressed, 0, gzBuffer, 4, compressed.Length);
System.Buffer.BlockCopy(BitConverter.GetBytes(buffer.Length), 0, gzBuffer, 0, 4);
return Convert.ToBase64String(gzBuffer);
}
//解壓縮
public string Decompress(string compressedText)
{
byte[] gzBuffer = Convert.FromBase64String(compressedText);
using (MemoryStream ms = new MemoryStream())
{
int msgLength = BitConverter.ToInt32(gzBuffer, 0);
ms.Write(gzBuffer, 4, gzBuffer.Length - 4);
byte[] buffer = new byte[msgLength];
ms.Position = 0;
using (GZipStream zip = new GZipStream(ms, CompressionMode.Decompress))
{
zip.Read(buffer, 0, buffer.Length);
}
return Encoding.Unicode.GetString(buffer);
}
}
#endregion
}
}
第二步.伺服器收到SQL語句執行,並回傳一個表給客戶端
伺服器接到請求,執行SQL語句返回一個DataTable
伺服器將這個DataTable進行序列化、並且壓縮
伺服器將【序列化和壓縮】後的byte[] msg數組傳給客戶端
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Net;
using System.Net.Sockets; //可以使用套接字
using System.Threading; //可以使用多線程
using System.Data.SqlClient;
using System.Xml;
using System.Xml.Serialization;
using System.IO;
using System.IO.Compression;
namespace AppServer
{
public partial class FormApp : Form
{
public FormApp()
{
InitializeComponent();
}
private void FormApp_Load(object sender, EventArgs e)
{
// AppService instance = new AppService();
}
private void buttonStartService_Click(object sender, EventArgs e)
{
AppService();
}
private Socket server;
private Socket client;
private void AppService()
{
/*
//本機IP
string name = Dns.GetHostName();
IPHostEntry host = Dns.GetHostByName(name);
IPAddress id= host.AddressList[0];
* */
//IPAddress local = IPAddress.Parse("192.168.0.100");
IPEndPoint iep = new IPEndPoint(IPAddress.Any, 6060);
server = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
// 將套接字與本地終結點綁定
server.Bind(iep);
//在本地13000埠號上進行監聽
server.Listen(10);
while (true)
{
// 得到包含客戶端信息的套接字
client = server.Accept();
//創建消息服務線程對象ClientService方法委託給線程
Thread newthread = new Thread(new ThreadStart(ClientService));
// 啟動消息服務線程
newthread.Start();
}
}
private Int32 i;
private void ClientService()
{
Socket s = client;
String data = null;
String returnData = null;
byte[] bytes = new byte[1024];
while ((i = s.Receive(bytes)) != 0)
{
//接收客戶端的SQL
data = System.Text.Encoding.Unicode.GetString(bytes, 0, i);
//將接到的String 執行SQL返回表
DBAccess obj = new DBAccess(); //專門傳給SQL的類相當於DBHELP
DataTable dt = obj.FillData(data, "TEST", 1);//執行SQL返回表
//將返回的表轉為String,並將returnData壓縮
returnData = obj.Compress(obj.SerializeDataTableXml(dt));
byte[] msg = System.Text.Encoding.Unicode.GetBytes(returnData);
// 發送數據表給客戶端 s.Send(msg);
if ((i = s.Receive(bytes)) == 0)
continue;
}
//關閉套接字
s.Close();
}
}
//DBAccess的部份代碼
class DBAccess
{
#region DataTable序列化與反序列化
public string SerializeDataTableXml(DataTable dt)
{
StringBuilder sb = new StringBuilder();
XmlWriter writer = XmlWriter.Create(sb);
XmlSerializer serializer = new XmlSerializer(typeof(DataTable));
serializer.Serialize(writer, dt);
writer.Close();
return sb.ToString(); }
public DataTable DeserializerDataTable(string pXml)
{
StringReader strReader = new StringReader(pXml);
XmlReader xmlReader = XmlReader.Create(strReader);
XmlSerializer serializer = new XmlSerializer(typeof(DataTable));
DataTable dt = serializer.Deserialize(xmlReader) as DataTable;
return dt; }
#endregion
#region 壓縮和解壓縮
public string Compress(string str)
{
byte[] buffer = Encoding.Unicode.GetBytes(str);
MemoryStream ms = new MemoryStream();
using (GZipStream zip = new GZipStream(ms, CompressionMode.Compress, true))
{
zip.Write(buffer, 0, buffer.Length);
}
ms.Position = 0;
MemoryStream outStream = new MemoryStream();
byte[] compressed = new byte[ms.Length];
ms.Read(compressed, 0, compressed.Length);
byte[] gzBuffer = new byte[compressed.Length + 4];
System.Buffer.BlockCopy(compressed, 0, gzBuffer, 4, compressed.Length);
System.Buffer.BlockCopy(BitConverter.GetBytes(buffer.Length), 0, gzBuffer, 0, 4);
return Convert.ToBase64String(gzBuffer);
}
public string Decompress(string compressedText)
{
byte[] gzBuffer = Convert.FromBase64String(compressedText);
using (MemoryStream ms = new MemoryStream())
{
int msgLength = BitConverter.ToInt32(gzBuffer, 0);
ms.Write(gzBuffer, 4, gzBuffer.Length - 4);
byte[] buffer = new byte[msgLength];
ms.Position = 0;
using (GZipStream zip = new GZipStream(ms, CompressionMode.Decompress))
{
zip.Read(buffer, 0, buffer.Length);
}
return Encoding.Unicode.GetString(buffer);
}
}
#endregion
}
第三步.調用DataSet和SqlDataAdapter.Update(Table)存在SQL中,這個是傳入一個DataGridView ,可在客戶端中使用保存(部份代碼,沒有連接SQL資料庫的)
#region 公共保存DataGridView
public bool DataGridViewSave(DataTable table,string tableName,string CorpCode)
{
string Sql = String.Format("Select Top 0 * From {0} Where CorpCode_='{1}' ", tableName, CorpCode);
SqlDataAdapter sda = new SqlDataAdapter(this.CreateCommand(Sql, null, 1));
SqlCommandBuilder scb = new SqlCommandBuilder(sda);
sda.Update(table);
this.Close();
return true;
}
#endregion
④ 如何使數據在客戶機和伺服器之間傳遞
我們還是從計算機的網路層說起,主要是分為7個層分別是物理層,數據鏈路層,網路層,升虧傳輸層,會話層,表示層,應用層。
數據之間的交互主要在傳輸層這一塊。通常用吵凳神到的底層協議有TCP和UDP這兩種協議。通過中間層SOCKET協議,進行包裝,再往上就是我們經常用到的HTTP協議。我們的網站就是通過HTTP協議進行客戶端和伺服器數據交互的。
HTTP協議是面向連接的協議基於TCP。按照三次握手四次揮手的規則進行數據交互。其中底層有用到網路套接字的概念。通過網路套接字,可以知道相互通信的IP地址和埠,這樣就像你打電話一樣,知道對方的手機號才能打給指定的人。
上面這個就是我們網站的http協議請求,裡面有請求頭,請求體。按照標準的約定去給服務端發送請求數據,然後服務端響應結果給客戶端。
同時我們的實時聊天軟體,比如今日頭條的聊天軟體就是通過TCP,SOCKET來進行通信的,這種是面向連接的長鏈接方式,雙向通信。響應指定封包協議和解包協議,通過socket的處理,去監聽兩端的埠,分別獲取各自的數據,和發送各自的數據。實現雙向通信。具體過程如下:
>客戶端步驟
1.創建套接字
2.向伺服器發送連接請求(connect)
3.通信(send/recv)
4.關閉套接字
>伺服器端步驟
1.創建用於監聽的套接字(socket)
2.將套接字綁定到本地地址和埠上(bind)
3.將套接字設為監聽模式(listen)
4.等待客戶請求(accept),此處粗啟要不斷的調用accept
5.通信(send/receive),完成後返回4
6.關閉套接字(closesocket)
謝謝閱讀,歡迎關注。
⑤ 伺服器計算機埠和客戶端計算機埠,如何實現相互通信的呢希望懂網路專…
TCP連接建立之後,伺服器和客戶端就可以互通數據了,可以通過HTTP、FTP、SMTP等等的協議進行各種應用,伺服器有通用的服務埠,例如80是HTTP服務,21是FTP服務,25是SMTP服務,這些埠號是通用的。而用戶的埠號則是不確定的。所以,客戶端需要某種服務時會先訪問伺服器的某個埠,並且通過TCP建立過程,告知伺服器自己的埠號。正如你所說的,黑客可以對客戶端偽裝成伺服器、對伺服器偽裝成客戶端,分別建立TCP連接,然後獲取用戶和伺服器的信息。現在很多釣魚陷阱就是這樣盜取用戶帳號、密碼的。木馬攻擊又是另外一回事了,木馬主要是把木馬程序載入用戶電腦,然後盜取用戶信息,當然通過中間人攻擊來注入木馬是常用的手段。
⑥ 如何實現通過伺服器,讓兩個客戶端互相通信
如果只是兩個客戶端和一個伺服器,可通過伺服器轉蘆如發即可,兩個客戶端連接到伺服器,伺服器把從A接收到的發給B,把從B接收到的發給A即可,如果要做成多個客戶端的,則要給各個客戶端分配ID,服務端好根據各個客戶端和消息要轉發送給客戶端陪桐啟的ID來確定消息發送對輪侍象。