请问:在编写winsock程序时,怎样调用CreateThread函数来创建进程(100分)

  • 主题发起人 主题发起人 driby
  • 开始时间 开始时间
D

driby

Unregistered / Unconfirmed
GUEST, unregistred user!
我在编写winsock程序时,使用CreateThead创建线程老是出错,程序如下:
procedure ClientThread(lpParam:Pointer); //该进程只是从客户端接收数据
var
sock:TSOCKET;
szBuff:array [1..80] of char;
fmtStr:String;
begin
sock:=TSOCKET(lpParam);
while true do
begin
// Perform a blocking recv() call
ret := recv(sock, szBuff, 80, 0);
if ret=0 then // Graceful close
break
else if ret=SOCKET_ERROR then
begin
fmtStr:=Format('recv() failed: %d',[WSAGetLastError()]);
ShowMessage(fmtStr);
break;
end;
fmtStr:='RECV: '+ szBuff;
ShowMessage(fmtStr);
end;
end;

在服务器主程序中调用如下:
var
... ...
fmtStr:String;
wVersionRequested:WORD;
sListen,sClient:TSocket;
hThread:Thandle;
ThreadID:DWord;
begin
... ...
while true do
begin
... ...
sClient := accept(sListen, @addr,@iAddrSize);
if sClient = INVALID_SOCKET then
begin
fmtStr:=Format('accept() failed: %d',[WSAGetLastError()]);
Label1.Caption:=fmtStr;
break;
end;

hThread := CreateThread(nil, 0, @ClientThread,@sClient, 0, ThreadID);
if hThread = NULL then
begin
fmtStr:=Format('CreateThread() failed: %d',[GetLastError()]);
Label1.Caption:=fmtStr;
break;
end;
CloseHandle(hThread);
end;
closesocket(sListen);
WSACleanup();
end;

 
怎么没人理我?
 
你给出的代码不完整,你叫我怎么开呀?ret 是什么?
 
Unit main;

Interface

Uses
Windows, SysUtils, Messages, Classes, Forms, ScktComp, Controls, StdCtrls,
Menus, Mask, Spin, ComCtrls, ExtCtrls;

Const
CM_IncCount = WM_USER + 1;

Type
TForm1 = Class(TForm)
ServerSocket: TServerSocket;
MainMenu: TMainMenu;
File1: TMenuItem;
ActiveItem: TMenuItem;
N1: TMenuItem;
Exit1: TMenuItem;
Panel1: TPanel;
Label1: TLabel;
CacheEdit: TSpinEdit;
Label2: TLabel;
PortEdit: TSpinEdit;
Label3: TLabel;
ThreadCount: TEdit;
Panel2: TPanel;
ListBox1: TListBox;
Panel3: TPanel;
StatusBar1: TStatusBar;
CharCount: TLabel;
Procedure ServerSocketGetThread(Sender: TObject;
ClientSocket: TServerClientWinSocket;
Var SocketThread: TServerClientThread);
Procedure FormCreate(Sender: TObject);
Procedure FormClose(Sender: TObject; Var Action: TCloseAction);
Procedure Exit1Click(Sender: TObject);
Procedure PortEditChange(Sender: TObject);
Procedure ActiveItemClick(Sender: TObject);
Procedure ServerSocketThreadEnd(Sender: TObject;
Thread: TServerClientThread);
Procedure ServerSocketThreadStart(Sender: TObject;
Thread: TServerClientThread);
Procedure CacheEditChange(Sender: TObject);
protected
Procedure CMIncCount(Var Msg: TMessage); message CM_IncCount;
public
End;

{ TFileServerThread }

TFileServerThread = Class(TServerClientThread)
public
Procedure ClientExecute; override;
End;

Var
Form1: TForm1;

Implementation

{$R *.DFM}

{ TFileServerThread }

Procedure TFileServerThread.ClientExecute;
Var
Data: Array[0..1023] Of char;
RecText: String;
SocketStream: TWinSocketStream;
Begin
While Not Terminated And ClientSocket.Connected Do
Try
SocketStream := TWinSocketStream.Create(ClientSocket, 30000);
Try
FillChar(Data, SizeOf(Data), 0);
If SocketStream.Read(Data, SizeOf(Data)) = 0 Then
Begin
// If we didn't get any data after xx seconds then close the connection
ClientSocket.SendText('Timeout on Server'+#13#10);
//Wait a little time to allow sending of text before disconnect
sleep(1);
ClientSocket.Close;
Terminate;
End;
RecText := Data;
If Length(RecText) > 2 Then
Delete(RecText, Pos(#13#10, RecText), 2); // Delete #13#10
If ClientSocket.Connected Then
Begin
ClientSocket.SendText(RecText);
SendMessage(Form1.Listbox1.Handle, LB_ADDSTRING, 0, Integer(PChar(RecText)));
PostMessage(Form1.Handle, CM_INCCOUNT, 0, 0);
End;
Finally
SocketStream.Free;
End;
Except
HandleException;
End;
End;

Procedure TForm1.ServerSocketGetThread(Sender: TObject;
ClientSocket: TServerClientWinSocket;
Var SocketThread: TServerClientThread);
Begin
// Create a new thread for connection
SocketThread := TFileServerThread.Create(False, ClientSocket);
ClientSocket.SendText('Welcome to Server'+#13#10);
End;

Procedure TForm1.FormCreate(Sender: TObject);
Begin
CacheEdit.Value := ServerSocket.ThreadCacheSize;
PortEdit.Value := ServerSocket.Port;
CharCount.Caption := '0';
ActiveItemClick(Nil);
End;

Procedure TForm1.FormClose(Sender: TObject; Var Action: TCloseAction);
Begin
ServerSocket.Close;
End;

Procedure TForm1.CMIncCount(Var Msg: TMessage);
Begin
CharCount.Caption := IntToStr(StrToInt(CharCount.Caption) + 1);
End;

Procedure TForm1.Exit1Click(Sender: TObject);
Begin
Close;
End;

Procedure TForm1.PortEditChange(Sender: TObject);
Begin
ServerSocket.Port := StrToInt(PortEdit.Text);
End;

Procedure TForm1.ActiveItemClick(Sender: TObject);
Begin
ServerSocket.Active := Not ServerSocket.Active;
ActiveItem.Checked := ServerSocket.Active;
If ServerSocket.Active Then
StatusBar1.SimpleText := 'Active'
Else
StatusBar1.SimpleText := 'InActive';
End;

Procedure TForm1.ServerSocketThreadEnd(Sender: TObject;
Thread: TServerClientThread);
Begin
ThreadCount.Text := IntToStr(StrToInt(ThreadCount.Text) - 1);
End;

Procedure TForm1.ServerSocketThreadStart(Sender: TObject;
Thread: TServerClientThread);
Begin
ThreadCount.Text := IntToStr(StrToInt(ThreadCount.Text) + 1);
End;

Procedure TForm1.CacheEditChange(Sender: TObject);
Begin
ServerSocket.ThreadCacheSize := CacheEdit.Value;
End;

End.

////////////////////
object Form1: TForm1
Left = 720
Top = 130
Width = 399
Height = 262
Caption = 'Server'
Color = clBtnFace
Font.Charset = DEFAULT_CHARSET
Font.Color = clWindowText
Font.Height = -11
Font.Name = 'MS Sans Serif'
Font.Style = []
Menu = MainMenu
OldCreateOrder = True
OnClose = FormClose
OnCreate = FormCreate
PixelsPerInch = 96
TextHeight = 13
object Panel1: TPanel
Left = 0
Top = 0
Width = 120
Height = 197
Align = alLeft
BevelOuter = bvNone
TabOrder = 0
object Label1: TLabel
Left = 8
Top = 5
Width = 94
Height = 13
Caption = 'Thread Cache Size:'
end
object Label2: TLabel
Left = 10
Top = 50
Width = 22
Height = 13
Caption = 'Port:'
end
object Label3: TLabel
Left = 10
Top = 91
Width = 65
Height = 13
Caption = 'Thread Count'
end
object CacheEdit: TSpinEdit
Left = 9
Top = 22
Width = 61
Height = 22
MaxValue = 20
MinValue = -1
TabOrder = 0
Value = 0
OnChange = CacheEditChange
end
object PortEdit: TSpinEdit
Left = 8
Top = 64
Width = 60
Height = 22
MaxLength = 4
MaxValue = 9000
MinValue = 1
TabOrder = 1
Value = 1
OnChange = PortEditChange
end
object ThreadCount: TEdit
Left = 8
Top = 107
Width = 62
Height = 21
Color = clBtnFace
ReadOnly = True
TabOrder = 2
Text = '0'
end
end
object Panel2: TPanel
Left = 120
Top = 0
Width = 271
Height = 197
Align = alClient
BevelOuter = bvNone
Caption = 'Panel2'
TabOrder = 1
object ListBox1: TListBox
Left = 0
Top = 21
Width = 271
Height = 176
Align = alClient
ItemHeight = 13
TabOrder = 0
end
object Panel3: TPanel
Left = 0
Top = 0
Width = 271
Height = 21
Align = alTop
Alignment = taLeftJustify
BevelOuter = bvNone
Caption = 'Chars Sent:'
TabOrder = 1
object CharCount: TLabel
Left = 55
Top = 4
Width = 50
Height = 13
Caption = 'CharCount'
end
end
end
object StatusBar1: TStatusBar
Left = 0
Top = 197
Width = 391
Height = 19
Panels = <>
SimplePanel = True
end
object ServerSocket: TServerSocket
Active = False
Port = 1024
ServerType = stThreadBlocking
OnGetThread = ServerSocketGetThread
OnThreadStart = ServerSocketThreadStart
OnThreadEnd = ServerSocketThreadEnd
Left = 315
Top = 1
end
object MainMenu: TMainMenu
Left = 350
Top = 1
object File1: TMenuItem
Caption = '&Server'
object ActiveItem: TMenuItem
Caption = '&Active'
OnClick = ActiveItemClick
end
object N1: TMenuItem
Caption = '-'
end
object Exit1: TMenuItem
Caption = 'E&xit'
OnClick = Exit1Click
end
end
end
end

////////////////////////////

program server;

uses
Forms,
main in 'main.pas' {Form1};

{$R *.RES}

begin
Application.Initialize;
Application.CreateForm(TForm1, Form1);
Application.Run;
end.

对你应该有用。
 
hThread := CreateThread(nil, 0, @ClientThread,@sClient, 0, ThreadID);
《windows程序设计》上说,线程函数必须声明为如下形式:
DWORD WINAPI ThreadProc(PVOID pParam);
至于在delphi里怎么声明就不清楚了,为什么不用TThread?
 
这样声明行不行?
procedure ClientThread(lpParam:Pointer);stdcall;
 
Error:
//procedure ClientThread(lpParam:Pointer): Integer; stdcall;
function ClientThread(lpParam:Pointer): Integer; stdcall;

var
sock:TSOCKET;
szBuff:array [1..80] of char;
fmtStr:String;
begin
Error:
// sock:=TSOCKET(lpParam);
sock := PInteger(lpParam)^;

TSocket(lpParam) ==>相当于 Integer(lpParam);把指针16进制转成10进制,而不找它的指向的socket值
 
后退
顶部