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. 分模块开发创建service子模块——(八)

    1.右击父工程新建maven子模块

  2. 如何新建Quartus工程—FPGA入门教程【钛白Logic】

    这一章我们来实现第一个FPGA工程—LED流水灯.我们将通过流水灯例程向大家介绍一次完整的FPGA开发流程,从新建工程,代码设计,综合实现,管脚约束,下载FPGA程序.掌握本章内容,大家就算正式的开始 ...

  3. BAT修改文本内容

    @echo off (for /f "delims=" %%a in (文件名) do ( set "str=%%a" setlocal enabledelay ...

  4. windows中连接hive-客户端

    参考连接:http://lxw1234.com/archives/2016/09/723.htm 这里主要介绍:Oracle SQL Developer 1. 下载,免安装包 SQL Develope ...

  5. 盒子模型与flex模型

    一.盒子模型 注意:两个相邻元素的margin值是重叠在一起的,取当中最大的那个值. 水平方向auto, margin:0 auto;会居中    但是margin-left:auto;,元素会到最右 ...

  6. 虚拟机Failed to start LSB: Bring up/down networking

      1.执行 service network restart 出现以下错误 Restarting network (via systemctl):  Job for network.service f ...

  7. java Stack(栈)

    "Stack" 通常时指"后进后出"(LIFO)的容器,有时栈也被称为叠加栈,因为最后"压入"栈的元素,第一个"弹出"栈 ...

  8. 如何让Ubuntu 12.04 LTS更炫更具吸引力

    Ubuntu 12.04 LTS震撼发布   适逢七周岁生日之际,Ubuntu正式推出了第四个LTS长期支持版本,开发代号Precise Pangolin的Ubuntu 12.04在2012年4月26 ...

  9. 【LOJ】#2122. 「HEOI2015」小 Z 的房间

    题解 又是一道取模不给质数的毒瘤矩阵树题 不会写分数类--然后发现了网上过于神仙的题解类似与辗转相除的这样把某一个位置消成0 orz 代码 #include <bits/stdc++.h> ...

  10. thinkphp中table方法

    table方法也属于模型类的连贯操作方法之一,主要用于指定操作的数据表. 用法 一般情况下,操作模型的时候系统能够自动识别当前对应的数据表,所以,使用table方法的情况通常是为了:切换操作的数据表: ...