① 如何实现客户端与服务器的交互
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来确定消息发送对轮侍象。