客户端远程访问服务端的SqlServer数据库问题

时间:2021-08-06 04:35:16
用ADO,在客户端通过_ConnectionPtr的Open("连接字符串")方法,将连接字符串中的Data Source改成服务端的IP地址,
那么可以在客户端远程打开服务端的数据库,再用_RecordsetPtr的GetCollect()方法可以取得数据库中对应表中的数据,
并通过客户端的控件将数据显示出来,也可以用_RecordsetPtr的PutCollect()修改服务端的数据库中表的能容,感觉很方便。

问题:如果有几万甚至几十万的客户端程序,通过IP地址操作服务端的数据库,我感觉这样访问数据库的效率肯定会低下,
就像大型网游我想客户端应该不是通过IP操作服务端的数据库的吧?那不通过IP怎么操作数据库呢?

能给个具体的方法吗?

14 个解决方案

#1


一般的客户端并不是直接去访问数据库的,中间通过服务器端程序转

#2


中间通过服务器端程序转,怎么转?能说的具体点吗?

#3


一般客户端不去连接数据库。
客户端的请求发给服务器程序后,服务器区数据库中进行操作,
并将结果放回给客户端。

#4


写一个服务器程序,所有的客户端都连接它,把要操作的命令发给服务器程序,由服务器程序去操作数据库,再将结果发回给客户端

#5


回4L大致了解,不过还有些具体的细节,我还要问下。
我现在要在客户端显示服务端数据库中表Table1的内容
Table1内容如下:
No    Name
1 Li Ming
2 Wang
根据4L的方法,是不是应该这样:

客户端程序:
通过socket连接服务端后,send(“select * from Table1”);


服务端程序:
_ _RecordsetPtr  m_Recordset
1.接收操作命令:Recv(&buf);
2.收到命令后用打开记录集:m_Recordset->Open(buf);
3.用一个while循环读取每条记录
_variant_t varNo,varName; //用于读取一条记录的各项
CString strSend=””; //用于将发送个客户端的内容组成一个字符串
While(!m_Recordset.IsEOF())
       {
 m_Recordset.GetCollect(“No”,varNo);//取得No
         strSend+=(LPCTSTR)(_bstr_t)varNo;//转换成字符型
  m_Recordset.GetCollect(“Name”,varName);
         strSend+=(LPCTSTR)(_bstr_t)varName; //取得Name
        m_Recordset.MoveNext();
       }
4:将读取的字符串(strSend)数据发送给客户端:send(strSend);

客户端程序:
1. 接收数据,recv(&buf);
2. 将buf拆分成一个个No,Name,以数据表的形式将内容显示在客户端

4L你觉得我的方法正确吗?有没有什么改进或注意的地方?

#6


这个方法也可以。
不过客户端通常不会直接发送SQL过去,
应该是逻辑抽象,类似于下面的。

1 C->S 请求用户列表
2 S    从数据库取得列表
3 S->C 返回取得的用户列表

#7


引用 5 楼 iorsafeqq22 的回复:
回4L大致了解,不过还有些具体的细节,我还要问下。
我现在要在客户端显示服务端数据库中表Table1的内容
Table1内容如下:
No Name
1 Li Ming
2 Wang
根据4L的方法,是不是应该这样:

客户端程序:
通过socket连接服务端后,send(“select * from Table1”);


服务端程序:
_ _RecordsetPtr m……


你这种方法也是可以的,服务器只管中转,由客户端处理,服务器的负载不会太大.

一般的做法正如六楼所讲,不会直接发送数据库命令的.客户端将所需要的参数信息发给服务器,服务器处理完后将给果返回给客户端

#8


6L的三步讲的有点抽象,我不太明白(老实说是不明白)各步具体做些什么?
能结合我给的具体例子讲讲吗?

在这先谢谢6L。

#9


7L说发送参数是指(以我的例子为例)只要发送表名(Table1),
send("Table1")
不要直接发送SQL语句是吧?

#10


该回复于2010-09-15 09:44:35被版主删除

#11


在5L的例子上做进一步的补充。
现在服务端数据库中变成了两个表:
Table1 Table2
No    Name ID    PassWord
1 LiMing         01 1234
2 Wang 02      5678
现在客户端在一个页面中单击按钮1显示Tabel1的能容,
在另一个页面中单击按钮2显示Table2的内容。

由于现在增加到了两个表,我想到在发送的结构体中加入
一个nType来标记从哪个表中度数据。

程序实现
构造发送的数据结构
Struct Data
{
UINT   nType;   //判断从哪个数据表中读取内容
//可以取值TABLE1 和TABEL2
CString  strTable;//要读取的数据表名称
}
客户端:
单击按钮1:send(Data(TABLE1,”Table1”);recv();
单击按钮2:send(Data(TABLE2,"Table2"

服务端:
Recv(&data);
_variant_t var;
Switch(data.nType)
{
Case TABLE1: 用m_Recorset->GetCollect(“No”,var)
                    读取Table1中信息,发送读取内容到客户端 break;
Case TABLE2: 用m_Recorset->GetCollect(“ID”,var)
                    读取TableL2中信息,发送读取内容到客户端 break;
}

但是如果要从服务端的几十个表中读取数据,就要设置几十个case,现在但是读要设置几十个case,
如果要写如数据库的话又要设置几十个case,感觉这样做case设置的太多了。
是不是我的方法不好啊?
大家有什么好方法吗?

#12


简单一点儿的,自定义一个数据传输格式:@@表名(动作)#字段名:值#字段名:值....
动作表示要操作数据库的命令
@@Table1(1)#No:*#Name:*#ID:*#Password:*


发送这个数据到服务器,服务器解析这个数据后生成sql命令,然后执行.

只需要这一个解析的东东就行了.

if(string头两字==@@)
{
   解析这个字符串
   sprintf(select 解析的值...)
}
执行这个语句
返回结果

客户端多的话,就一个线程接收生成命令,一个线程执行命令,生成结果,一个传送结果

#13


回水无痕
这方法不错,比我的好太多了。
多谢你的认真回答。

PS:你是不是从事这方面开发的啊。

#14


结贴了,再次感谢水无痕

#1


一般的客户端并不是直接去访问数据库的,中间通过服务器端程序转

#2


中间通过服务器端程序转,怎么转?能说的具体点吗?

#3


一般客户端不去连接数据库。
客户端的请求发给服务器程序后,服务器区数据库中进行操作,
并将结果放回给客户端。

#4


写一个服务器程序,所有的客户端都连接它,把要操作的命令发给服务器程序,由服务器程序去操作数据库,再将结果发回给客户端

#5


回4L大致了解,不过还有些具体的细节,我还要问下。
我现在要在客户端显示服务端数据库中表Table1的内容
Table1内容如下:
No    Name
1 Li Ming
2 Wang
根据4L的方法,是不是应该这样:

客户端程序:
通过socket连接服务端后,send(“select * from Table1”);


服务端程序:
_ _RecordsetPtr  m_Recordset
1.接收操作命令:Recv(&buf);
2.收到命令后用打开记录集:m_Recordset->Open(buf);
3.用一个while循环读取每条记录
_variant_t varNo,varName; //用于读取一条记录的各项
CString strSend=””; //用于将发送个客户端的内容组成一个字符串
While(!m_Recordset.IsEOF())
       {
 m_Recordset.GetCollect(“No”,varNo);//取得No
         strSend+=(LPCTSTR)(_bstr_t)varNo;//转换成字符型
  m_Recordset.GetCollect(“Name”,varName);
         strSend+=(LPCTSTR)(_bstr_t)varName; //取得Name
        m_Recordset.MoveNext();
       }
4:将读取的字符串(strSend)数据发送给客户端:send(strSend);

客户端程序:
1. 接收数据,recv(&buf);
2. 将buf拆分成一个个No,Name,以数据表的形式将内容显示在客户端

4L你觉得我的方法正确吗?有没有什么改进或注意的地方?

#6


这个方法也可以。
不过客户端通常不会直接发送SQL过去,
应该是逻辑抽象,类似于下面的。

1 C->S 请求用户列表
2 S    从数据库取得列表
3 S->C 返回取得的用户列表

#7


引用 5 楼 iorsafeqq22 的回复:
回4L大致了解,不过还有些具体的细节,我还要问下。
我现在要在客户端显示服务端数据库中表Table1的内容
Table1内容如下:
No Name
1 Li Ming
2 Wang
根据4L的方法,是不是应该这样:

客户端程序:
通过socket连接服务端后,send(“select * from Table1”);


服务端程序:
_ _RecordsetPtr m……


你这种方法也是可以的,服务器只管中转,由客户端处理,服务器的负载不会太大.

一般的做法正如六楼所讲,不会直接发送数据库命令的.客户端将所需要的参数信息发给服务器,服务器处理完后将给果返回给客户端

#8


6L的三步讲的有点抽象,我不太明白(老实说是不明白)各步具体做些什么?
能结合我给的具体例子讲讲吗?

在这先谢谢6L。

#9


7L说发送参数是指(以我的例子为例)只要发送表名(Table1),
send("Table1")
不要直接发送SQL语句是吧?

#10


该回复于2010-09-15 09:44:35被版主删除

#11


在5L的例子上做进一步的补充。
现在服务端数据库中变成了两个表:
Table1 Table2
No    Name ID    PassWord
1 LiMing         01 1234
2 Wang 02      5678
现在客户端在一个页面中单击按钮1显示Tabel1的能容,
在另一个页面中单击按钮2显示Table2的内容。

由于现在增加到了两个表,我想到在发送的结构体中加入
一个nType来标记从哪个表中度数据。

程序实现
构造发送的数据结构
Struct Data
{
UINT   nType;   //判断从哪个数据表中读取内容
//可以取值TABLE1 和TABEL2
CString  strTable;//要读取的数据表名称
}
客户端:
单击按钮1:send(Data(TABLE1,”Table1”);recv();
单击按钮2:send(Data(TABLE2,"Table2"

服务端:
Recv(&data);
_variant_t var;
Switch(data.nType)
{
Case TABLE1: 用m_Recorset->GetCollect(“No”,var)
                    读取Table1中信息,发送读取内容到客户端 break;
Case TABLE2: 用m_Recorset->GetCollect(“ID”,var)
                    读取TableL2中信息,发送读取内容到客户端 break;
}

但是如果要从服务端的几十个表中读取数据,就要设置几十个case,现在但是读要设置几十个case,
如果要写如数据库的话又要设置几十个case,感觉这样做case设置的太多了。
是不是我的方法不好啊?
大家有什么好方法吗?

#12


简单一点儿的,自定义一个数据传输格式:@@表名(动作)#字段名:值#字段名:值....
动作表示要操作数据库的命令
@@Table1(1)#No:*#Name:*#ID:*#Password:*


发送这个数据到服务器,服务器解析这个数据后生成sql命令,然后执行.

只需要这一个解析的东东就行了.

if(string头两字==@@)
{
   解析这个字符串
   sprintf(select 解析的值...)
}
执行这个语句
返回结果

客户端多的话,就一个线程接收生成命令,一个线程执行命令,生成结果,一个传送结果

#13


回水无痕
这方法不错,比我的好太多了。
多谢你的认真回答。

PS:你是不是从事这方面开发的啊。

#14


结贴了,再次感谢水无痕