Peter Kiers
asked on
Combine 2 units.
Hello Experts,
I have found source code of a Telnet emulator-programm that makes
a connection to a mainframe.
On the form is a TImage-component that is the 3270-screen
and it uses 2 units, one for creating the connection (winsock) and the
other is used when the connection has been established a thread is created
to receive data from the remote host. So, when the first unit has made
the connection it calls the Thread that is specified in the second unit.
type
RecvThrd = class(TThread)
private
IOSocket: TSocket ;
{ Private declarations }
protected
etc.. etc…
Is it possible to combine these 2 units to 1? Because in the unit where
the connection is created I miss the structure of the unit, and in the second
unit there is class specified.
This is the first unit:
unit telnetu;
interface
uses
Windows, Winsock, Messages, SysUtils,
Classes, Dialogs;
procedure TcpStartup ;
procedure TcpCleanup ;
procedure Log(str: string) ;
procedure Disconnect ;
procedure SendData(sdata: string) ; //calls the RecvThrd = class(TThread)
procedure MakeConnect ;
implementation
uses
Screenu, utilu ;
etc.. etc..
Second unit:
unit RecThrd;
interface
uses
Windows, Winsock, Messages, SysUtils,
Classes ;
const
IO_BUF_SIZE = 4096 ;
type
RecvThrd = class(TThread)
private
IOSocket: TSocket ;
{ Private declarations }
protected
procedure Log(str: string) ;
procedure DumpChar(ch: char) ;
procedure DumpFlush ;
procedure DispChar(ch: byte) ;
procedure ProcessDataStream ;
procedure LogDisp ;
procedure Display ;
procedure Execute; override;
public
constructor Create(ios: TSocket) ;
end;
TBuf = array[0..IO_BUF_SIZE] of char ;
threadvar
s: string[16] ;
numchars: integer ;
bytecnt: integer ;
etc.. etc...
Greetings,
Peter Kiers
I have found source code of a Telnet emulator-programm that makes
a connection to a mainframe.
On the form is a TImage-component that is the 3270-screen
and it uses 2 units, one for creating the connection (winsock) and the
other is used when the connection has been established a thread is created
to receive data from the remote host. So, when the first unit has made
the connection it calls the Thread that is specified in the second unit.
type
RecvThrd = class(TThread)
private
IOSocket: TSocket ;
{ Private declarations }
protected
etc.. etc…
Is it possible to combine these 2 units to 1? Because in the unit where
the connection is created I miss the structure of the unit, and in the second
unit there is class specified.
This is the first unit:
unit telnetu;
interface
uses
Windows, Winsock, Messages, SysUtils,
Classes, Dialogs;
procedure TcpStartup ;
procedure TcpCleanup ;
procedure Log(str: string) ;
procedure Disconnect ;
procedure SendData(sdata: string) ; //calls the RecvThrd = class(TThread)
procedure MakeConnect ;
implementation
uses
Screenu, utilu ;
etc.. etc..
Second unit:
unit RecThrd;
interface
uses
Windows, Winsock, Messages, SysUtils,
Classes ;
const
IO_BUF_SIZE = 4096 ;
type
RecvThrd = class(TThread)
private
IOSocket: TSocket ;
{ Private declarations }
protected
procedure Log(str: string) ;
procedure DumpChar(ch: char) ;
procedure DumpFlush ;
procedure DispChar(ch: byte) ;
procedure ProcessDataStream ;
procedure LogDisp ;
procedure Display ;
procedure Execute; override;
public
constructor Create(ios: TSocket) ;
end;
TBuf = array[0..IO_BUF_SIZE] of char ;
threadvar
s: string[16] ;
numchars: integer ;
bytecnt: integer ;
etc.. etc...
Greetings,
Peter Kiers
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
YES,YES,YES
I have got it.
change it to: RecvThrd.Create(soc);
And it works thanks to you.
Greetings,
Peter Kiers
I have got it.
change it to: RecvThrd.Create(soc);
And it works thanks to you.
Greetings,
Peter Kiers
Glad to help.
ASKER
[Error] telnetu.pas(432): Incompatible types: 'RecThrd.RecvThrd' and 'telnetu.RecvThrd'
at line:
RecThread := RecvThrd.Create(soc) ;
This is the whole unit:
unit telnetu;
interface
uses
Windows, Winsock, Messages, SysUtils,
Classes, Dialogs;
const
IO_BUF_SIZE = 4096 ;
type
RecvThrd = class(TThread)
private
IOSocket: TSocket ;
{ Private declarations }
protected
procedure ProcessDataStream ;
procedure Execute; override;
public
constructor Create(ios: TSocket) ;
end;
TBuf = array[0..IO_BUF_SIZE] of char ;
procedure TcpStartup ;
procedure TcpCleanup ;
procedure Log(str: string) ;
procedure Disconnect ;
procedure SendData(sdata: string) ;
procedure MakeConnect ;
threadvar
s: string[16] ;
numchars: integer ;
bytecnt: integer ;
implementation
uses
Screenu, utilu ;
procedure TcpStartup ;
var
err: integer ;
VersionReq: word ;
wsaData: TWSAData ;
begin
VersionReq := $0101 ;
err := WSAStartup(VersionReq,wsaD
end ;
procedure TcpCleanup ;
var
err: integer ;
begin
err := WSACancelBlockingCall() ;
err := WSACleanup() ;
end ;
procedure Log(str: string) ;
begin
ShowMessage(str) ;
end ;
procedure DumpChar(ch: char) ;
var
sf: string ;
ic: integer ;
i: integer ;
e: char ;
begin
etc…
procedure DumpFlush ;
var
sf: string ;
ic: integer ;
i: integer ;
e: char ;
begin
etc…
procedure Disconnect ;
begin
if RecThreadRunning then
RecThread.Terminate() ;
if socOpen then
begin
closesocket(soc) ;
socOpen := false ;
end ;
TcpCleanup() ;
if deb then
Log('TCP Ended.') ;
end;
procedure SendData(sdata: string) ;
const
C_CR = $0A ; { carrage return }
C_LF = $0D ; { line feed }
type
TOutBuf = array[0..4096] of char ;
var
err: integer ;
size: integer ;
pc: PChar ;
OutBuffer: TOutBuf ;
i: integer ;
begin
if EorFlag then
sdata := sdata + Char(IAC) + Char(C_EOR) ;
pc := @OutBuffer ;
StrPCopy(pc,sdata) ;
size := Length(sdata) ;
err := send(soc,OutBuffer,size,0)
if err = SOCKET_ERROR then
Log('Send error: '
+Format('%d',[WSAGetLastEr
else
begin
if deb then
begin
Log('Send: '+Format(' (%d)',[size])) ;
for i:=0 to (size-1) do
DumpChar(OutBuffer[i]) ;
DumpFlush ;
end ;
end ;
end;
procedure MakeConnect ;
type
TPint = ^Longint ;
var
err: integer ;
phost: PHostEnt ;
ina: TInAddr ;
lina: TInAddr ;
pint: TPint ;
RemoteHostName: TPath ;
PRemoteHostName: PChar ;
LocalHostName: TPath ;
PLocalHostName: PChar ;
LocalAddr: TSockAddrIn ;
psaddr: PSockAddr ;
RemoteAddr: TSockAddrIn ;
pServAddr: PServEnt ;
usPort: u_short ;
InitCmd: string ;
NonBlocked: u_long ;
begin
TcpStartup() ;
if deb then
Log('TCP Started.') ;
soc := socket(AF_INET, SOCK_STREAM, IPPROTO_TCP) ;
if soc = INVALID_SOCKET then
begin
Log('Error socket invalid.') ;
socOpen := False ;
end
else
begin
if deb then
Log('Socket opened OK.') ;
socOpen := True ;
end ;
{ get foreign host name and addr }
PRemoteHostName := @RemoteHostName ;
StrPCopy(PRemoteHostName,C
phost := gethostbyname(PRemoteHostN
if phost = nil then
begin
Log('Error, failed to find host.') ;
Disconnect ;
end
else
begin
if deb then
begin
Log('Foreign host name: '
+PChar(phost^.h_name)) ;
Log(' Address type: '
+format('%x',[phost^.h_add
Log(' Address length: '
+format('%d',[phost^.h_len
end ;
pint := Pointer(phost^.h_addr_list
ina.s_addr := pint^ ;
if deb then
Log(' Foreign host address: '
+PChar(inet_ntoa(ina))) ;
{ get local host name and addr }
PLocalHostName := @LocalHostName ;
if gethostname(PLocalHostName
begin
phost := gethostbyname(PLocalHostNa
if phost = nil then
begin
Log('Error, failed to find local host.') ;
Disconnect ;
end
else
begin
if deb then
begin
Log('Local host name: '
+PChar(phost^.h_name)) ;
Log(' Address type: '
+format('%x',[phost^.h_add
Log(' Address length: '
+format('%d',[phost^.h_len
end ;
pint := Pointer(phost^.h_addr_list
lina.s_addr := pint^ ;
if deb then
Log(' Local host address: '
+PChar(inet_ntoa(lina))) ;
{ bind socket to addr }
LocalAddr.sin_family := AF_INET ;
LocalAddr.sin_addr.s_addr := lina.s_addr ;
LocalAddr.sin_port := htonl(INADDR_ANY) ;
psaddr := Pointer(@LocalAddr) ;
err := bind(soc,psaddr^,SizeOf(Lo
if err = SOCKET_ERROR then
begin
Log('Bind error: '
+Format('%d',[WSAGetLastEr
Disconnect ;
end
else
begin
if deb then
Log('Bind successful') ;
{ get service port }
pServAddr := getservbyname('telnet','tc
if pServAddr <> nil then
begin
if deb then
begin
Log('Remote Service Info.:') ;
Log(' Name: '+PChar(pServAddr^.s_name)
Log(' Port: '+Format('%d',[ntohs(pServ
end ;
usPort := pServAddr^.s_port ;
{ connect to server }
RemoteAddr.sin_family := AF_INET ;
RemoteAddr.sin_addr.s_addr
RemoteAddr.sin_port := usPort ;
psaddr := Pointer(@RemoteAddr) ;
err := connect(soc,psaddr^,SizeOf
if err = SOCKET_ERROR then
begin
Log('Connect error: '
+Format('%d',[WSAGetLastEr
Disconnect ;
end
else
begin
if deb then
Log('Connected.') ;
{ start thread to receive all data - will
also do all telnet negotiation }
RecThread := RecvThrd.Create(soc) ;
{ send CR LF to get server started }
SendData(InitCmd) ;
end ;
end
else
begin
Log('Getservbyname error: '
+Format('%d',[WSAGetLastEr
Disconnect ;
end ;
end ;
end ;
end
else
begin
Log('Get local host error:'
+Format('%d',[WSAGetLastEr
Disconnect ;
end ;
end ;
end;
{ RecvThrd }
constructor RecvThrd.Create(ios: TSocket);
var
i: integer ;
begin
FreeOnTerminate := True ;
IOSocket := ios ;
numchars := 0 ;
for i := 1 to 16 do
s[i] := chr(0) ;
inherited Create(False) ; { dont run thread yet }
end ;
procedure RecvThrd.Execute;
type
PTelCmd = ^TTelCmd ;
TTelCmd = packed record
c_iac: Byte ;
c_cmd: Byte ;
c_func: Byte ;
end ;
PTelTermCmd = ^TTelTermCmd ;
TTelTermCmd = packed record
c_iac: Byte ;
c_sb: Byte ;
c_term: Byte ;
c_is: Byte ;
c_type: array[1..10] of char ;
c_iace: Byte ;
c_se: Byte ;
end ;
etc…
procedure RecvThrd.ProcessDataStream
begin
// Ds3270.DataIn(DataStreamBu
end;
end.
Greetings,
Peter