http://blog.csdn.net/lailai186/article/details/8788710?utm_source=tuicool

TClientSocket和TServerSocket的数据通知使用了Windwos下的消息通知机制,造成它们只适合针对窗口的WinForm程序,因为可以得到窗口的Handle句柄,用来postmessage或者sendmessage,但对于Dll这样的不存在窗口的工程就不适应了,我做了测试:

在DLL工程中引入TClientSocket,设置HostIP,HostPort后,Active后开始send数据,然后Active设置false关闭连接,但服务端没有收到数据,server端的ClientReadr事件不能被调用。

所以考虑一下还是用Windows的API来实现标准的Socket连接,结果通讯可以得到数据了。一下是实现代码,贴出来希望对做D7Socket的DLL需求的哥们有个帮助。

Server端代码:

{*************************************************
**uSocketFasca
@note:winsock 服务程序封装类

}

unit uSocketFasca;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, ComCtrls, StdCtrls, WinSock,LoggerU; //定义socket传输的数据结构
type
PPACKDATA=^TPACKDATA;
TPACKDATA=record
cmd:string[];
data:string[];
id:LongInt;
end; //定义服务数据获取线程
TServerThread=class(TThread)
private
FSocket:Integer;
g_preId:Integer;
protected
procedure Execute; override;
procedure DecvDataLoop;
public
constructor Create(SockHd:Integer);
end; //定义server启动线程
TInvokerThread=class(TThread)
private
m_serversocket:Integer;
m_clientsocket:Integer;
m_serveraddr:sockaddr_in;
Client_Addr: TSockAddr;
ClientLen: Integer;
FHostIp:string;
FHostPort:Integer;
protected
procedure Execute;override;
//初始化并启动服务
procedure InitAndStartServerSocket;
//释放WInSOck
procedure WSACleanup();
procedure InitLogger();
public
constructor Create(HostIp:string;HostPort:Integer);
end; var
FLogger:TLogger; implementation {TInvokerThread}
procedure TInvokerThread.InitLogger();
begin
FLogger:=TLogger.GetLoggerInstance('uSocketFasca');
end; //初始化并启动服务socket
procedure TInvokerThread.InitAndStartServerSocket;
var
XL_WSADATA:TWSAData;
Ret:Integer;
threadFunc:TServerThread;
tm : Longint;
begin
//init winsock 2.0 libaray
Ret:=WSAStartup(MakeWord(,),XL_WSADATA);
if (<>Ret) then
begin
FLogger.Send('WSASetUp error!');
Exit;
end;
//create socket
m_serversocket:=socket(PF_INET,SOCK_STREAM,);
if INVALID_SOCKET = m_serversocket then
begin
FLogger.Send('Create socket error!');
Exit;
end;
tm:=;//非锁定模式 ;TM:=0锁定模式
ioctlsocket(m_serversocket,FIONBIO,tm);
//bind socket
m_serveraddr.sin_family:=PF_INET ;
m_serveraddr.sin_port:=htons(FHostPort);
m_serveraddr.sin_addr.S_addr:=INADDR_ANY;
Ret:=bind(m_serversocket,m_serveraddr,SizeOf(m_serveraddr));
if Ret=SOCKET_ERROR then
begin
FLogger.Send('socket bind error!');
Exit;
end;
//linsten
Ret:=listen(m_serversocket,);
if Ret=SOCKET_ERROR then
begin
FLogger.Send('listen socket error!');
Exit;
end;
m_clientsocket:=INVALID_SOCKET;
while(True) do
begin
if terminated then
begin
threadFunc.Terminate;
exit;
end;
//阻塞模式
FillChar(Client_Addr,Sizeof(Client_Addr),);
ClientLen := Sizeof(Client_Addr);
m_clientsocket:=accept(m_serversocket,@Client_Addr,@ClientLen) ;
if m_clientsocket <> INVALID_SOCKET then
begin
threadFunc:=TServerThread.Create(m_clientsocket);
end;
Application.ProcessMessages;
end;
Application.ProcessMessages;
end; procedure TInvokerThread.WSACleanup();
begin
closesocket(m_serversocket);
end; constructor TInvokerThread.Create(HostIp: string; HostPort: Integer);
begin
inherited Create(False);
FHostIp:=HostIp;
FHostPort:=HostPort;
FreeOnTerminate:=True;
InitLogger;
end; procedure TInvokerThread.Execute;
begin
inherited;
Synchronize(InitAndStartServerSocket);
if Terminated then Exit;
end; { TServerThread } constructor TServerThread.Create(SockHd: Integer);
begin
inherited Create(False);
FSocket:=SockHd;
FreeOnTerminate:=True;
g_preId:=-;
end; procedure TServerThread.DecvDataLoop;
var
Buff:TPACKDATA;
SendBuf:string[];
RET: Integer;
FdSet : TFDSet;
TimeVal : TTimeVal;
begin while(true) do
begin
if terminated then exit;
//非阻塞模式
FD_ZERO(FdSet);
FD_SET(FSocket,FdSet);
TimeVal.tv_sec:=;
TimeVal.tv_usec:=;
if (select(,@FdSet,nil,nil,@TimeVal)>) and (not terminated) then
begin
Ret:=recv(FSocket,Buff,SizeOf(Buff),);
if RET=SOCKET_ERROR then
begin
FLogger.Send('Read Error!');
Continue;
end;
if RET > then
begin
if (g_preId<>Buff.id) then begin
g_preId:=Buff.id;
FLogger.Send('Recv Cmd:'+Buff.cmd) ;
FLogger.Send('Recv Data:'+Buff.Data) ;
FLogger.Send('Recv Id:'+inttostr(Buff.id)) ;
SendBuf:='Rec OK';
send(FSocket,SendBuf,SizeOf(SendBuf),);
break; end; end;
end; //end select
end; end; procedure TServerThread.Execute;
begin
inherited;
Synchronize(DecvDataLoop);
if Terminated then Exit;
end; end. 调用逻辑: unit uMain; interface uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, uSocketFasca, StdCtrls; type
TForm1 = class(TForm)
Button1: TButton;
btn1: TButton;
procedure Button1Click(Sender: TObject);
procedure btn1Click(Sender: TObject);
procedure FormClose(Sender: TObject; var Action: TCloseAction); private
{ Private declarations }
invoker:TInvokerThread;
public
{ Public declarations }
end; var
Form1: TForm1; implementation {$R *.dfm} procedure TForm1.Button1Click(Sender: TObject);
var
HostIp,HostPort:string;
begin
HostIp:='192.168.50.1';
HostPort:='';
invoker:=TInvokerThread.Create(HostIp,StrToInt(HostPort));
end; procedure TForm1.btn1Click(Sender: TObject);
begin
showmessage('@!@');
end; procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
invoker.Terminate;
//TerminateThread(invoker.Handle,0); end; end.

客户端

unit uSocketLibrary;

interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, ComCtrls, StdCtrls, WinSock,LoggerU; type
PPACKDATA=^TPACKDATA;
TPACKDATA=record
cmd:string[];
data:string[];
id:LongInt;
end; TClient_Socket=class
private
FLogger:TLogger;
client_socket:Integer;
Fhost_port:Integer;
client_hostent:PHostEnt;
client_addr:TSockAddrIn;
psaddr:^LongInt;
saddr:LongInt;
Fhost_ip:string;
public
procedure DisconnectServer();
function ConnectionServer():Integer;
function SendData(buff:TPACKDATA): integer;
function RecvData():integer;
constructor Create(IpAddr:string;HostPort:Integer);
end;
implementation { TClient_Socket } function TClient_Socket.ConnectionServer: Integer;
var
Clt_WSADATA:TWSAData;
Ret:Integer;
begin
Ret:=WSAStartup(MakeWord(,),Clt_WSADATA);
if (<>Ret) then
begin
FLogger.Send('WSASetUp error!');
Result:=;
Exit;
end;
client_addr.sin_family:=PF_INET;
client_addr.sin_port:=htons(Fhost_port);
client_hostent:=gethostbyname(PChar(Fhost_ip)) ;
if nil=client_hostent then
begin
saddr:=inet_addr(PChar(Fhost_ip));
if -<>saddr then
client_addr.sin_addr.S_addr:=saddr;
end
else
begin
psaddr:=Pointer(client_hostent.h_addr_list^);
client_addr.sin_addr.S_addr:=psaddr^;
end;
client_socket:=socket(PF_INET,SOCK_STREAM,);
if INVALID_SOCKET = client_socket then
begin
FLogger.Send('create socket fail!');
Result:=;
exit;
end;
Ret:=connect(client_socket,client_addr,SizeOf(client_addr));
if socket_error = Ret then
begin
closesocket(client_socket);
FLogger.Send('Connect fail!');
Result:=;
exit;
end;
Result:=;
end; constructor TClient_Socket.Create(IpAddr: string; HostPort: Integer);
begin
FLogger:=TLogger.GetLoggerInstance('SocketLibaray');
Fhost_ip:=IpAddr;
Fhost_port:=HostPort;
end; procedure TClient_Socket.DisconnectServer;
begin
shutdown(client_socket,SD_SEND);
closesocket(client_socket);
end; function TClient_Socket.RecvData: integer;
var
buff:string[];
ret:integer;
begin
Result:=;
ret:=recv(client_socket,buff,SizeOf(buff),);
if (SOCKET_ERROR=ret) then
begin
FLogger.Send('Read Error!');
Result:=;
Exit;
end
else if ret> then
begin
if (buff='Rec OK') then
Result:=;
end;
end; function TClient_Socket.SendData(buff:TPACKDATA): integer;
var
//strBuf:string[254];
ret:Integer;
begin
ret:=send(client_socket,buff,SizeOf(buff),);
Result:=;
end; end. DLL工程逻辑: library PrjDLL; { Important note about DLL memory management: ShareMem must be the
first unit in your library's USES clause AND your project's (select
Project-View Source) USES clause if your DLL exports any procedures or
functions that pass strings as parameters or function results. This
applies to all strings passed to and from your DLL--even those that
are nested in records and classes. ShareMem is the interface unit to
the BORLNDMM.DLL shared memory manager, which must be deployed along
with your DLL. To avoid using BORLNDMM.DLL, pass string information
using PChar or ShortString parameters. } uses
SysUtils,
Classes,
uSocketLibrary in 'uSocketLibrary.pas'; function ConnectServerAndSendData(IpAddr:string;RPort:string;buffer:TPACKDATA):integer;stdcall;
var
clt:TClient_Socket;
hostIp,sPort,sData:string;
hostPort:Integer;
begin
hostIp:=IpAddr;
sPort:=RPort;
//sData:=;
hostPort:=StrToInt(sPort);
clt:=TClient_Socket.Create(hostIp,hostPort);
try
if clt.ConnectionServer= then
begin
if clt.SendData(buffer)= then
begin
while(clt.RecvData=) do
begin
Result:=;
break;
end;
end;
end;
finally
clt.DisconnectServer;
clt.Free;
end;
Result:=;
end; exports ConnectServerAndSendData; {$R *.res} begin end.

好了,整个过程代码都在这了。有需要的兄弟可以贴下来试试,我是用Delphi7编译并测试通过的。希望有所帮助!

delphi socket 编程 使用多线程的更多相关文章

  1. 初涉Delphi Socket编程

    不是第一次接触socket编程了,但以前都是看别人的依葫芦画瓢,也不知道具体的原理. 新的项目,有了新的开始,同时也需要有新的认识. Delphi 中带有两套TCP Socket组件: Indy So ...

  2. Android应用开发提高篇(4)-----Socket编程(多线程、双向通信)

    链接地址:http://www.cnblogs.com/lknlfy/archive/2012/03/04/2379628.html 一.概述 关于Socket编程的基本方法在基础篇里已经讲过,今天把 ...

  3. Delphi Socket通信及多线程编程总结

    http://cxhblog.blog.sohu.com/41930676.html 一.Socket通信: Delphi在ScktComp单元中对WinSock进行了封装,该单元提供了TAbstra ...

  4. Python学习笔记——进阶篇【第八周】———进程、线程、协程篇(Socket编程进阶&多线程、多进程)

    本节内容: 异常处理 Socket语法及相关 SocketServer实现多并发 进程.线程介绍 threading实例 线程锁.GIL.Event.信号量 生产者消费者模型 红绿灯.吃包子实例 mu ...

  5. 为什么socket编程要用到多线程

    不得不佩服计算机先驱的设计:socket编程为什么需要多线程.如果只有一个ServerSocket线程,那么如下代码: public void start() throws Exception { S ...

  6. 使用libevent进行多线程socket编程demo

    最近要对一个用libevent写的C/C++项目进行修改,要改成多线程的,故做了一些学习和研究. libevent是一个用C语言写的开源的一个库.它对socket编程里的epoll/select等功能 ...

  7. socket编程,简单多线程服务端测试程序

    socket编程,简单多线程服务端测试程序 前些天重温了MSDN关于socket编程的WSAStartup.WSACleanup.socket.closesocket.bind.listen.acce ...

  8. 多线程Java Socket编程示例

    package org.merit.test.socket; import java.io.BufferedReader; import java.io.IOException; import jav ...

  9. 多线程编程以及socket编程_Linux程序设计4chapter15

    看了Linux程序设计4中文版,学习了多线程编程和socket编程.本文的程序参考自Linux程序设计4的第15章. 设计了一个客户端程序,一个服务端程序.使用TCP协议进行数据传输. 客户端进程创建 ...

随机推荐

  1. Hibernate5总结

    1. 明确Hibernate是一个实现了ORM思想的框架,它封装了JDBC,是程序员可以用对象编程思想来操作数据库. 2. 明确ORM(对象关系映射)是一种思想,JPA(Java Persistenc ...

  2. 【干货】查看windows文件系统中的数据—利用簇号查看文件与恢复文件

    前面我们使用这个软件发现了很多删除掉的数据,今天来看看簇.FAT文件系统中,存在一个簇的链接,我知道了簇1在哪里就可以顺藤摸瓜恢复所有的信息. 这里使用FAT 12为例子,FAT其他万变不离其宗,甚至 ...

  3. ARM linux内核启动时几个关键地址【转】

    转自:http://www.cnblogs.com/armlinux/archive/2011/11/06/2396787.html 1.       内核启动地址1.1.   名词解释ZTEXTAD ...

  4. KVM -> 虚拟化简介&虚拟机安装_01

    什么是虚拟化? 在计算机技术中,虚拟化(技术)或虚拟技术(英语:Virtualization)是一种资源管理技术,是将计算机的各种实体资源(CPU.内存.磁盘空间.网络适配器等),予以抽象.转换后呈现 ...

  5. SUSE Enterprise Server 12 SP3 64 设置防火墙开放8080端口,出现Unsafe permissions for file /etc/sysconfig/SuSEfirewall2 to be sourced

    SUSE Enterprise Server  12 SP3 64 设置防火墙开放8080端口时出现  Unsafe permissions for file /etc/sysconfig/SuSEf ...

  6. MCS-51 单片机的中断系统

    MCS-51 单片机的中断系统 MCS-51中断系统:5个中断源(两个外部中断, 两个定时器, 一个串口),2个优先级 中断相关概念 中断:当CPU正在处理某件事情时,单片机外部或内部发生的某一紧急事 ...

  7. 几个node项目实例-《转载》

    1. 词搜索 根据一个特效匹配模式搜索整个英语词典词.这个程序是一个相当实在的应用.有足够的不平常代码,帮助你学习NodeJS应用架构以及如何使用NodeJS做一些有用的平台. 它使用expressw ...

  8. sed的一些使用技巧

    一.当一个文件里有两行相同的内容,但这时只想修改第一行的内容或者第二行的内容,而不是全部修改,以下例子说明下: 1.修改匹配到第一行为port的内容(若要真修改前面记得-i): [root suppo ...

  9. 1 、在Linux(centos6.8)系统下的JDK安装与配置

    一.解压jdk安装包: 附上jdk1.8的下载地址: http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-21 ...

  10. 只想写一个真正能用的django mock

    调参数的过程,百转千回. 还好,搞得差不多了. 确实,方便写测试用例, 也是一个开发水平高低的衡量~~~:( 为了测试这个mock,不得不改下代码~~ 还要不断的将Model里允许Null的参数写完, ...