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. 【ARTS】01_06_左耳听风-20181217~1223

    ARTS: Algrothm: leetcode算法题目 Review: 阅读并且点评一篇英文技术文章 Tip/Techni: 学习一个技术技巧 Share: 分享一篇有观点和思考的技术文章 Algo ...

  2. Linux驱动中completion接口浅析(wait_for_complete例子,很好)

    completion是一种轻量级的机制,它允许一个线程告诉另一个线程工作已经完成.可以利用下面的宏静态创建completion:                          DECLARE_CO ...

  3. bulk_write&Replace_one

    ns=[]ns.append(ReplaceOne({'ip': ok['ip']}, ok, upsert=True))#更新插入 if len(ns) > 0: res = coll.bul ...

  4. webpack2.0学习

    1.进到指定的目录下,新建自己的文件名 mkdir webpack-test 创建你的项目名称或者你己有的项目名称cd webpack-test npm initnpm install webpack ...

  5. GET和POST两种基本请求方法的区别(转载)

    get与post请求的区别: 通常回答: GET在浏览器回退时是无害的,而POST会再次提交请求. GET产生的URL地址可以被Bookmark,而POST不可以. GET请求会被浏览器主动cache ...

  6. elasticsearch6.3.2之x-pack6.3.2破解安装并配合kibana使用

    原文链接:https://www.plaza4me.com/article/20180825223826278 由于在elasticsearch在6.3版本之后x-pack是默认安装好的,所以不再需要 ...

  7. CI框架中集成CKEditor编辑器的教程

    CKEditor是在很多开发过程中都会用到的一个富文本编辑器,那么如何在CI框架中使用它呢?这里介绍了在CI下使用CKEditor的方法,版本比较低,是在CI 1.7.3下使用fckeditor 2. ...

  8. CSS------ul与div如何排成一行

    如图: 代码:(需要给div的float属性设置为left) <div style="margin-top:10px"> <div style="flo ...

  9. 【Java】 二叉树的遍历(递归与循环+层序遍历)

    在[Java] 大话数据结构(9) 树(二叉树.线索二叉树)一文中,已经实现了采用递归方法的前.中.后序遍历,本文补充了采用循环的实现方法.以及层序遍历并进行了一个总结. 递归实现 /* * 前序遍历 ...

  10. 【Ray Tracing in One Weekend 超详解】 光线追踪1-2

    今天我们开始进入正篇 Chapter 3: Rays, a simple camera, and background 对于所有的光线追踪器,基本都有一个光线类,计算沿光线看到的颜色. 我们的光线是一 ...