我在线程中定义了一个ClientSocket1,然后由主程序向其提供参数,主要提供ip地址和端口,但是总在这两个地方提示读某某地址错误,下面是我得主要代码:
begin
EnterCriticalSection(CriticalSection);
FillChar(xinxi,sizeof(xinxi),0);//每次赋值前,填充0
ClientSocket1.Address:=ip;//ip为全局变量
ClientSocket1.port:=port;//port为全局变量
ClientSocket1.Active:=true;
//下面1到9句是我自定义的一个记录结构
1 xinxi.m_msg := 3; //操作码
2 xinxi.filename := 'user.ini'; //文件名或其它的
3 xinxi.user := 'test'; //用户名
4 xinxi.PworCrc := 'test'; //密码或CRC值
5 xinxi.SESSION := session; //连接标志,用来保持连接的
6 xinxi.m_ok := 0;
7 //xinxi.Filesize := 9; //文件大小
8 xinxi.m_begin := 0; //开始字
9 xinxi.m_end := 0; //结
ClientSocket1.Socket.SendBuf(xinxi, sizeof(xinxi));
while ClientSocket1.Socket.ReceiveLength=0 do
begin
// sleep(10); //加上后,程序出问题
application.ProcessMessages;
end;
ClientSocket1.Socket.ReceiveBuf(xinxi, sizeof(xinxi));
i:=xinxi.m_ok;
if i=1 then
showmessage('服务器没有此文件');
if i=0 then
begin
AssignFile(ToF, 'c:\s.txt');
ss:=GetFileSize('c:\s.txt');
Reset(tof,1);
seek(tof,ss);
showmessage(inttostr(sizeof('c:\s.txt')));
while xinxi.Filesize>0 do
begin
while ClientSocket1.Socket.ReceiveLength=0 do
begin
application.ProcessMessages;
end;
read:=ClientSocket1.Socket.ReceiveBuf(buf,sizeof(buf)); BlockWrite(Tof,buf,read);
xinxi.Filesize := xinxi.Filesize - read; end;
CloseFile(Tof); end;
LeaveCriticalSection(CriticalSection);
ExitThread(4);
end;调用线程:
procedure TForm1.Button1Click(Sender: TObject);
var
ThreadId1: DWORD;
begin
ip:='192.168.0.11';//全局变量
port:=2007;//全局变量
InitializeCriticalSection(CriticalSection);
CreateThread(nil, 0, @ThreadFunc, nil, 0, ThreadId1);
end;
begin
EnterCriticalSection(CriticalSection);
FillChar(xinxi,sizeof(xinxi),0);//每次赋值前,填充0
ClientSocket1.Address:=ip;//ip为全局变量
ClientSocket1.port:=port;//port为全局变量
ClientSocket1.Active:=true;
//下面1到9句是我自定义的一个记录结构
1 xinxi.m_msg := 3; //操作码
2 xinxi.filename := 'user.ini'; //文件名或其它的
3 xinxi.user := 'test'; //用户名
4 xinxi.PworCrc := 'test'; //密码或CRC值
5 xinxi.SESSION := session; //连接标志,用来保持连接的
6 xinxi.m_ok := 0;
7 //xinxi.Filesize := 9; //文件大小
8 xinxi.m_begin := 0; //开始字
9 xinxi.m_end := 0; //结
ClientSocket1.Socket.SendBuf(xinxi, sizeof(xinxi));
while ClientSocket1.Socket.ReceiveLength=0 do
begin
// sleep(10); //加上后,程序出问题
application.ProcessMessages;
end;
ClientSocket1.Socket.ReceiveBuf(xinxi, sizeof(xinxi));
i:=xinxi.m_ok;
if i=1 then
showmessage('服务器没有此文件');
if i=0 then
begin
AssignFile(ToF, 'c:\s.txt');
ss:=GetFileSize('c:\s.txt');
Reset(tof,1);
seek(tof,ss);
showmessage(inttostr(sizeof('c:\s.txt')));
while xinxi.Filesize>0 do
begin
while ClientSocket1.Socket.ReceiveLength=0 do
begin
application.ProcessMessages;
end;
read:=ClientSocket1.Socket.ReceiveBuf(buf,sizeof(buf)); BlockWrite(Tof,buf,read);
xinxi.Filesize := xinxi.Filesize - read; end;
CloseFile(Tof); end;
LeaveCriticalSection(CriticalSection);
ExitThread(4);
end;调用线程:
procedure TForm1.Button1Click(Sender: TObject);
var
ThreadId1: DWORD;
begin
ip:='192.168.0.11';//全局变量
port:=2007;//全局变量
InitializeCriticalSection(CriticalSection);
CreateThread(nil, 0, @ThreadFunc, nil, 0, ThreadId1);
end;
2、把IP和PORT定义成一个记录类型:
PNetInfo=^TNetInfo;
TNetInfo=record
IP: array[0..19] of Char;
PORT: WORD;
end;
3、在CreateThread函数参数里传递指针:
p_NetInfo: PNetInfo;
CreateThread(nil, 0, @ThreadFunc, p_NetInfo, 0, ThreadId1);
4、在线程函数里尽量用WINSOCK原生函数,和WIN32函数。
5、熟练使用指针。这点对写好网络程序非常重要。
unit Unit1;interfaceuses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, ScktComp;
type
PNetInfo=^TNetInfo;
TNetInfo=record
IP: array[0..19] of Char;
PORT: WORD;
end;
type
client_record1 = record
m_msg: integer; //操作码
filename: array[0..254] of char; //文件名或其它的
user: array[0..31]of char; //用户名
PworCrc: array[0..31]of char; //密码或CRC值
SESSION: integer; //连接标志,用来保持连接的
m_ok: integer;
Filesize: int64; //文件大小
m_begin: int64; //开始字
m_end: int64; //结束
end;
type
TForm1 = class(TForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;var
Form1: TForm1;
kk:client_record1;
implementation{$R *.dfm}
function EnumFileInRecursion(p: PNetInfo):Longint;stdcall;
var
cs: TClientSocket;
begin
cs.Address:=p.IP;
cs.Port:=p.PORT;
cs.Active:=true; FillChar(kk,sizeof(kk),0);//每次赋值前,必须填充0
kk.m_msg := 1; //操作码
kk.filename := 'user.ini'; //文件名或其它的
kk.user := 'test'; //用户名
kk.PworCrc := 'test'; //密码或CRC值
// xinxi.SESSION := session; //连接标志,用来保持连接的
kk.m_ok := 0;
//xinxi.Filesize := 9; //文件大小
kk.m_begin := 0; //开始字
kk.m_end := 0; //结
cs.Socket.SendBuf(kk, sizeof(kk));
while cs.Socket.ReceiveLength=0 do
begin
// sleep(10); //加上后,程序出问题
application.ProcessMessages;
end;
//cs.Socket.ReceiveBuf(kk, sizeof(kk));
showmessage(cs.Socket.RemoteHost);
end;
procedure TForm1.Button1Click(Sender: TObject);
var
dwThreadID:Cardinal;
p_NetInfo: PNetInfo;
begin
p_NetInfo.IP:='192.168.1.234';
p_NetInfo.port:=2007;
CreateThread(nil,0,@EnumFileInRecursion,p_NetInfo,0,dwThreadID);
end;
end.
function EnumFileInRecursion(p: PNetInfo):Longint;stdcall;
var
cs: TClientSocket;
begin
cs.Address:=p.IP;
cs.Port:=p.PORT;
cs.Active:=true;
showmessage(cs.Socket.RemoteHost);
end;
错误提示project main.exe raised exception class EInOutError with message'I/O error 103' process stopped.use step or run to continue.。
但是我创建列表后,关掉程序重新打开,再下载都没有错.提示行在
assignfile(file1,'.\temp\'+extractfilename(s1));
// FileMode:=1;
rewrite(file1); //---->这一行处错
建议先判断文件是否存在FileExists,如果存在使用Append,否则才是ReWrite啊
直接用api创建线程,变量地址空间是不同的,所以传入指针参数在线程执行过程中指向别的位置.
所以为p_NetInfo: PNetInfo动态分配内存可以解决该问题(不推荐这样做);
p_NetInfo:=getmem(PNetInfo,sizeof(p_NetInfo: TNetInfo));
用完后再释放freemem(p_NetInfo)