关于局域网文件传输的问题,熟悉网络编程的朋友请进。。。。

kingcaiyao 2002-11-26 05:09:48
上个星期季世平JSP给了一个关于局域网文件文件传输的例子,效果还不错,不过我想将这个例子封装成函数,也就是说我不需要用户界面,而用程序接口,因为我要做的系统中文件传输只是一个很小的子功能,因此我想将它封装成DLL或COM,但我对SOCKET编程这一套东西不是很熟,而且根据的编程思路,将文件的上传和下载封装成几个输出函数,具体来说封装成以下几个函数:SendFile,GetFile,SendMsg这几个函数,现在还没有会么头绪,请各位网络方面的高手给予指点,不胜感谢。。。。
...全文
63 54 打赏 收藏 转发到动态 举报
写回复
用AI写文章
54 条回复
切换为时间正序
请发表友善的回复…
发表回复
shclhs 2002-11-29
  • 打赏
  • 举报
回复
请叫他的全名“瘩蚊蜥"
呵呵~~~~~
大哥写好,我一定参观
daniel_tao 2002-11-29
  • 打赏
  • 举报
回复
小小建议,如果把通讯的程序写到DLL中会对通讯的速度有一定的影响.所以我个人认为没有必要写成DLL
daniel_tao 2002-11-28
  • 打赏
  • 举报
回复
up
copy_paste 2002-11-28
  • 打赏
  • 举报
回复
“龇牙咧嘴”

上面的字打了我一分种,所以用Zzzzz~~~~~


Zzzzzz~~~~~~
RomanticProgrammer 2002-11-28
  • 打赏
  • 举报
回复
"Zzzzz~~~~~~~"是什么意思啊.?
copy_paste 2002-11-28
  • 打赏
  • 举报
回复
没问题啦?我可是一大堆BUG,调了半天,都是些指针,气死我了,平常都不错,关键时候出错,找都找不出来。

你的代码中没有应答部分,还可以再简单点,就是发送时,将数据一次性发送出去就完了,不过可能会占用一会的CPU吧(100%的那种,连mouse都不会动),然后使劲接收就是了。不过也看情况,文件太大了,速度就直线下降了。
一般我在做应答时,发送数据的单位一般是:5k<->10K左右吧,这个速度比较快了。

-----------------------
有分接哦,快快去哦。。。

Zzzzz~~~~~~~
kingcaiyao 2002-11-28
  • 打赏
  • 举报
回复
再次谢谢JSP和copy_paste的指点,请copy_paste到下贴中取分:
http://expert.csdn.net/Expert/topic/1209/1209380.xml?temp=.272442
RomanticProgrammer 2002-11-28
  • 打赏
  • 举报
回复
学习...向伟大得JSP和copy_paste学习.
jishiping 2002-11-27
  • 打赏
  • 举报
回复
我说的只是将通讯有关的代码封装到一个DLL里。对于服务器而言,只调用服
务器的函数,对于客户端程序而言,只调用客户端的函数。在DLL里并不执行
实现的通讯处理代码。实际的通讯处理代码由EXE完成,然后将EXE写的函数
作为回调函数传给DLL,让DLL调用就可以了。我的意思就是这样。当然,对于
一个EXE来说,也可以同时实现服务器和客户端的功能,就是说,可以同时接
收别人传过来的文件,也可以将文件传给其它的机器。当然了,这是在2个线
程中完成的。不知道我这样说,你明白了没有。
copy_paste 2002-11-27
  • 打赏
  • 举报
回复
mark
有时间看看。:)
kingcaiyao 2002-11-27
  • 打赏
  • 举报
回复
JSP,我另外开了一张贴子给分你,请接分:
http://expert.csdn.net/Expert/topic/1209/1209368.xml?temp=.3957025
kingcaiyao 2002-11-27
  • 打赏
  • 举报
回复
先谢谢JSP。
JSP兄,你谈到可以封装成一个DLL,这个我认为好像不容易实现,我昨天想了一下因为这本身涉及到网络编程,有一个服务器端和多个客户端,如果你封装成一个DLL,那是不是要在DLL写一个输出函数,将指定IP地址的服务器的端口打开进行监听,然后接受客户端的请求,你的思路是不是这样的?
jishiping 2002-11-27
  • 打赏
  • 举报
回复
在服务器的EXE部分,写一个回调函数:
void SrvCallback(TServerClientWinSocket* socket)
{
//这儿写代码,就省略了
}

在EXE的开始,调用DLL的设定函数,如:
SetSrvParam(100, SrvCallback);
这样就完成了服务器端DLL的所有封装和实现代码。对于客户端,原理一样。
jishiping 2002-11-27
  • 打赏
  • 举报
回复
不一定要2个DLL,可以将客户端和服务器端封装成一个DLL(当然也可以分开
做成两个DLL了,这在于你自己)。至于“上述程序中有关服务器开辟线程接
收数据的代码移到一个工程中去”,这样的话,对服务器的设定,需要这样一
个函数,设定监听Port和回调函数就可以了。这样收到部分的处理代码由EXE
部分完成。服务器端的代码如下:

//srvdll.h
typedef void (*ServerFun)(TServerClientWinSocket* socket);
extern "C" BOOL __declspec(dllexport) __stdcall SetSrvParam(
int Port, ServerFun func);
//

//unit2.h (服务器的头文件)
#ifndef Unit2H
#define Unit2H
//-----------------------------------------------------------------
#include <Classes.hpp>
#include <Controls.hpp>
#include <StdCtrls.hpp>
#include <Forms.hpp>
//-----------------------------------------------------------------class TDataModule1 : public TDataModule
{
__published: // IDE-managed Components
TServerSocket *ServerSocket1;
void __fastcall ServerSocket1GetThread(TObject *Sender,
TServerClientWinSocket *ClientSocket,
TServerClientThread *&SocketThread);
private: // User declarations
public: // User declarations
__fastcall TDataModule1(TComponent* Owner);
};

class SrvThread : public TServerClientThread
{
private:
TWinSocketStream* WskStream;
protected:
void __fastcall ClientExecute();
public:
__fastcall SrvThread(TServerClientWinSocket*);
};
//------------------------------------------------------------------
extern PACKAGE TDataModule1 *DataModule1;


//unit2.cpp (服务器的代码)
#include <vcl.h>
#pragma hdrstop

#include "Unit2.h"
#include "srvdll.h"
//-----------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TDataModule1 *DataModule1;
//-----------------------------------------------------------------
extern ServerFun SrvFunc;

__fastcall TDataModule1::TDataModule1(TComponent* Owner)
: TDataModule(Owner)
{
}
//-----------------------------------------------------------------
void __fastcall TDataModule1::ServerSocket1GetThread(TObject *Sender,
TServerClientWinSocket *ClientSocket, TServerClientThread *&SocketThread)
{
SocketThread = new SrvThread(ClientSocket);
}
//-----------------------------------------------------------------
__fastcall SrvThread::SrvThread(TServerClientWinSocket* socket)
: TServerClientThread(false,socket)
{
}
//-----------------------------------------------------------------
void __fastcall SrvThread::ClientExecute()
{
try {
if (SrvFunc != NULL)
SrvFunc(ClientSocket);
}
catch(Exception& e) {
MessageBox(0, e.Message.c_str(), "Error",
MB_ICONERROR|MB_SERVICE_NOTIFICATION);
}
try {
ClientSocket->Close();
}
catch(...) {
}
}

//DLL的主程序
#include <vcl.h>
#include <windows.h>
#pragma hdrstop
#pragma argsused
#include "Unit2.h"
#include "srvdll.h"

ServerFun SrvFunc = NULL;
int WINAPI DllEntryPoint(HINSTANCE hinst, DWORD reason, void*)
{
if (reason==DLL_PROCESS_ATTACH)
DataModule1 = NULL;

return 1;
}
//-----------------------------------------------------------------
extern "C" __declspec(dllexport)
BOOL __stdcall SetSrvParam(int Port, ServerFun func)
{
ServerFun = func;

if (DataModule1 == NULL)
DataModule1 = new TDataModule1(0);
if (Port!=Module1->ServerSocket1->Port) {
Module1->ServerSocket1->Active = 0;
Module1->ServerSocket1->Port = Port;
}
try {
Module1->ServerSocket1->Active = 1;
}
catch(Exception& e) {
MessageBox(0, e.Message.c_stR(), "Error",
MB_ICONERROR|MB_SERVICE_NOTIFICATION);
}
return Module1->ServerSocket1->Active ? 1 : 0;
}
kingcaiyao 2002-11-27
  • 打赏
  • 举报
回复
TO JSP:
谢谢你的意见,不过如果按照你的意思,是不是要讲客户端和服务器端封装成两个DLL呢,我不知道有没有理解错,我是想将客户端它封装成一个DLL,另外将上述程序中有关服务器开辟线程接收数据的代码移到一个工程中去,让它生成一个EXE,每次要通信,必须首先打开这个服务程序对客户端进行监听,这是我的编程思路.你详细说明一下你的思路.
copy_paste 2002-11-27
  • 打赏
  • 举报
回复
还有Client和Server之间通讯的协议比较重要,比如说你以后想做断点续传的,你就得定义些通讯的协议,其实说白了,就是开始通讯的时间,前面的几个字节是一些你特定的数据。如:
typedef struct
{
int command;
int count;
BYTE content[MAX_COUNT];
}

每次根据command作出不同反应,就传文件来说,第一,传送方要传文件名给被传送方吧,然后再转File content,文件传完后,如遇到需要valid/check CRC,你还得传CRC值给它,再返回,再say:transfer over.

如果遇到断点传,那就麻烦了,一个线程传还马马虎虎,得到当前文件Size,给传输方,然后从那里开始就行了,如果是多个线程传一个文件,得记录每个线程的断点,结束点,再开始传,我这段做这个,简直就。。。逻辑就快把我弄晕了。
pzoon 2002-11-27
  • 打赏
  • 举报
回复
收藏一下。
copy_paste 2002-11-27
  • 打赏
  • 举报
回复
unsigned long ServerSocketThread(void* lpParam)
{
TMsg msg;
PeekMessage(msg, 0, 0, 0, PM_NOREMOVE);
while (1)
{
if (PeekMessage(msg, 0, 0, 0, PM_REMOVE))
{
swtich(msg.wParam)
{
case 0:
...
case 1:
...
}
}
else
WaitMessage();
}
}

unsigned long CreateServerSocket(int Port)
{
TServerWinSocket *Socket = new TServerWinSocket(INVALID_SOCKET);
unsigned long ThreadID;
HANDLE Handle = CreateThread(NULL, 0, ServerSocketThread, (void*)Socket, 0, &ThreadID);
CloseHandle(Handle);
reuturn ThreadID;
}

随手写个大概,如果还想有其它参数,如回调或是结构指针,在Create时声明,传给线程,并返回线调用者。
勉励前行 2002-11-27
  • 打赏
  • 举报
回复
收藏一下。
copy_paste 2002-11-27
  • 打赏
  • 举报
回复
可以这样,在Server中起个线程,并创建消息队伍,然后while (1),不断接收你控制的命令,如:
SendFile(hServer, 1, (int)(void*)FileName);
SendMsg(hServer, 2, (int)(void*)Msg);

在while(1)中一直循环,直接接收到某个特定消息结束。

其实就像是File操作一样。
CreateFile ==》CreateServerSocket
新建一个线程再listen Socket ,返回ThreadID,你的程序就保留这个ThreadID,
然后用这个ThreadID,来控制。

Client就容易了。给个回调函数就什么都完了。像CopyFileEx一样。
加载更多回复(34)

13,825

社区成员

发帖
与我相关
我的任务
社区描述
C++ Builder相关内容讨论区
社区管理员
  • 基础类社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧