我在线程中定义了一个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;

解决方案 »

  1.   

    我要做的是一个socket的多线程点对点下载程序,如果有源码同样给分。
      

  2.   

    1、尽量少定义全局变量。
    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、熟练使用指针。这点对写好网络程序非常重要。
      

  3.   

    老大,下面是我的代码,还是有点问题,好像是内存读写问题,请帮我看看错在什么地方。谢谢
    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.
      

  4.   

    不好意思,忘了kk也用指针传,但是我把所有与kk有关的内容屏蔽后只剩一下几句还是有错。
    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; 
     
      

  5.   

    这个问题我已经解决了,主要原因是我使用了showmessage;还有问题继续问大家:就是怎样在线程中实现我上面程序的功能。现在的现象是通过大体如上的结构能实现连接服务器,但是服务器不能接收到(或者说我这边没有发送登陆消息过去)。
      

  6.   

    还有个问题向大家请教 我先创建下载列表,然后点下载,就出错
    错误提示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); //---->这一行处错
      

  7.   

    rewrite是文件不存在的情况下使用的啊,如果存在肯定要报错的啊
    建议先判断文件是否存在FileExists,如果存在使用Append,否则才是ReWrite啊
      

  8.   

    最好继承TThread类创建线程类
    直接用api创建线程,变量地址空间是不同的,所以传入指针参数在线程执行过程中指向别的位置.
    所以为p_NetInfo: PNetInfo动态分配内存可以解决该问题(不推荐这样做); 
    p_NetInfo:=getmem(PNetInfo,sizeof(p_NetInfo: TNetInfo));
    用完后再释放freemem(p_NetInfo)