unit Unit1;interfaceuses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs,IdWinSock2, StdCtrls;
//用了Indy9的IdWinSock2单元
type
TForm1 = class(TForm)
Memo1: TMemo;
Button1: TButton;
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
SocketArray:array[0..wsa_maximum_wait_events-1] of TSocket;
EventArray:array[0..wsa_maximum_wait_events-1] of wsaevent;
NewEvent:wsaevent;
NetWorkEvents:TWSANetworkEvents;
InternetAddr:TSockAddrIn;
AcceptSkt,ListenSkt:TSocket;
EventTotal:DWORD;
index:DWORD;
{ Public declarations }
end;var
Form1: TForm1;implementation//书上原文没有这个CompressArrays函数,按照自己的理解写了这个函数实现的内容
procedure CompressArrays(var pEventArray:array of wsaevent;pSocketArray:array of TSocket;var nEventTotal:DWORD;const nIndex:Integer);
var
i:integer;
begin
for i:=nIndex to Length(pEventArray)-2 do
begin
pEventArray[i]:=pEventArray[i+1];
pSocketArray[i]:=pSocketArray[i+1];
end;
pEventArray[Length(pEventArray)-1]:=0;
pSocketArray[Length(pEventArray)-1]:=0;
Dec(nEventTotal);
end;{$R *.dfm}procedure TForm1.FormCreate(Sender: TObject);
var
WSAData:TWSADATA;
begin
//1.初始化 WinSock
if (WSAStartup(MakeWord(2,0),WSAData)<>0) then
begin
//初始化失败
Memo1.Lines.Add('Winsock Init Failed');
Exit;
end
else
Memo1.Lines.Add('Socket Start');
end;procedure TForm1.FormDestroy(Sender: TObject);
begin
WSACleanup;
end;procedure TForm1.Button1Click(Sender: TObject);
var
i:integer;
buffer:PChar;
begin
EventTotal:=0;
NewEvent:=0;
GetMem(buffer,1024);//自己加的 ListenSkt:=socket(pf_inet,sock_stream,0);
InternetAddr.sin_family:=af_inet;
InternetAddr.sin_addr.S_addr:=htonl(inaddr_any);
InternetAddr.sin_port:=htons(5150); bind(ListenSkt,@InternetAddr,SizeOf(InternetAddr)); NewEvent:=WSACreateEvent();//这里出错,提示Access violation at address 00000000.Read of address 00000000. WSAEventSelect(ListenSkt,NewEvent,fd_accept or fd_close); listen(ListenSkt,5);
SocketArray[EventTotal]:=ListenSkt;
EventArray[EventTotal]:=NewEvent; while True do
begin
//等候所有套接字上的网络事件
Index:=WSAWaitForMultipleEvents(EventTotal,@EventArray,False,wsa_infinite,False);
Index:=index-wsa_wait_event_0; //遍历所有事件,查看被传信的事件是否多于一个
for i:=index to EventTotal-1 do
begin
Index:=WSAWaitForMultipleEvents(1,@(EventArray[i]),True,1000,False);
if (index=WSA_Wait_Failed) or (index=WSA_wait_timeout) then
Continue
else begin
Index:=i;
WSAEnumNetworkEvents(SocketArray[index],EventArray[index],@NetWorkEvents); //检查FD_Accept消息
if (NetWorkEvents.lNetworkEvents and fd_accept)<>0 then
begin
if NetWorkEvents.iErrorCode[FD_Accept_bit]<>0 then
begin
Memo1.Lines.Add('FD_Accept failed with error '+IntToStr(NetWorkEvents.iErrorCode[fd_accept_bit]));
Break;
end; //接受一个新连接,并将它添加到套接字及事件列表中
AcceptSkt:=accept(Socketarray[index],nil,nil); //无法处理多于WSA_MAXIMUM_WAIT_EVENTS数量的套接字,故关闭接受套接字
if EventTotal>=WSA_MAXIMUM_WAIT_EVENTS then
begin
Memo1.Lines.Add('Too ManyConnections');
closesocket(AcceptSkt);
Break;
end; NewEvent:=WSACreateEvent(); WSAEventSelect(AcceptSkt,NewEvent,fd_read or fd_write or fd_close); Inc(EventTotal);
EventArray[EventTotal]:=NewEvent;
SocketArray[EventTotal]:=AcceptSkt;
//原文在这里Inc(EventTotal),我觉得应该写到前两行去
Memo1.Lines.Add('Socket '+IntToStr(AcceptSkt)+' Connected!');
end; //处理FD_Read通知
if (NetWorkEvents.lNetworkEvents and FD_read)<>0 then
begin
if (NetWorkEvents.iErrorCode[FD_read_Bit]<>0) then
begin
Memo1.Lines.Add('FD_read failed with error '+IntToStr(NetWorkEvents.iErrorCode[fd_read_bit]));
Break;
end;
//从套接字读入数据
ZeroMemory(buffer,SizeOf(buffer));
recv(socketarray[index-wsa_wait_event_0],buffer,SizeOf(buffer),0);
Memo1.Lines.Add('Socket ['+IntToStr(socketarray[index-wsa_wait_event_0])+'] Recv:'+buffer);
end; //处理FD_WRITE通知
if (NetWorkEvents.lNetworkEvents and FD_Write)<>0 then
begin
if NetWorkEvents.iErrorCode[fd_write_bit]<>0 then
begin
Memo1.Lines.Add('FD_Write failed with error '+IntToStr(NetWorkEvents.iErrorCode[fd_write_bit]));
break;
end;
send(SocketArray[index-wsa_wait_event_0],buffer,SizeOf(buffer),0);
Memo1.Lines.Add('Socket ['+IntToStr(Socketarray[index])+'] Send something...');
end; if (NetWorkEvents.lNetworkEvents and FD_Close)<>0 then
begin
if NetWorkEvents.iErrorCode[FD_close_bit]<>0 then
begin
Memo1.Lines.Add('FD_Close failed with error '+Inttostr(NetWorkEvents.iErrorCode[FD_close_bit]));
Break;
end;
closesocket(Socketarray[index]);
Memo1.Lines.Add('Socket ['+IntToStr(Socketarray[index])+'] Close !'); //从Socket和Event数组删除套接字与其关联的事件,并递减EventTotal
CompressArrays(EventArray,SocketArray,EventTotal,index);
end;
end;
end;
end;
FreeMem(buffer);
Memo1.Lines.Add('Server Exit!')
end;end.------------------------------
窗体上只有一个Memo1组件和一个Button1启动按钮,大家可以直接拷贝代码调试。执行到NewEvent:=WSACreateEvent();时提示错误:Access violation at address 00000000.Read of address 00000000.看了一些帖子,提示可能是内存未分配导致的,不过自己不知道要怎么改。
也有帖子写有好像需要手动加载WS2_32.dll,不过也试过,好像不行。
不知道有没有朋友遇到过类似问题,怎么解决的,指点一下。
环境:Delphi7+Indy9+XP,代码使用的I/O模型是WSAventSelect模型。
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs,IdWinSock2, StdCtrls;
//用了Indy9的IdWinSock2单元
type
TForm1 = class(TForm)
Memo1: TMemo;
Button1: TButton;
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
SocketArray:array[0..wsa_maximum_wait_events-1] of TSocket;
EventArray:array[0..wsa_maximum_wait_events-1] of wsaevent;
NewEvent:wsaevent;
NetWorkEvents:TWSANetworkEvents;
InternetAddr:TSockAddrIn;
AcceptSkt,ListenSkt:TSocket;
EventTotal:DWORD;
index:DWORD;
{ Public declarations }
end;var
Form1: TForm1;implementation//书上原文没有这个CompressArrays函数,按照自己的理解写了这个函数实现的内容
procedure CompressArrays(var pEventArray:array of wsaevent;pSocketArray:array of TSocket;var nEventTotal:DWORD;const nIndex:Integer);
var
i:integer;
begin
for i:=nIndex to Length(pEventArray)-2 do
begin
pEventArray[i]:=pEventArray[i+1];
pSocketArray[i]:=pSocketArray[i+1];
end;
pEventArray[Length(pEventArray)-1]:=0;
pSocketArray[Length(pEventArray)-1]:=0;
Dec(nEventTotal);
end;{$R *.dfm}procedure TForm1.FormCreate(Sender: TObject);
var
WSAData:TWSADATA;
begin
//1.初始化 WinSock
if (WSAStartup(MakeWord(2,0),WSAData)<>0) then
begin
//初始化失败
Memo1.Lines.Add('Winsock Init Failed');
Exit;
end
else
Memo1.Lines.Add('Socket Start');
end;procedure TForm1.FormDestroy(Sender: TObject);
begin
WSACleanup;
end;procedure TForm1.Button1Click(Sender: TObject);
var
i:integer;
buffer:PChar;
begin
EventTotal:=0;
NewEvent:=0;
GetMem(buffer,1024);//自己加的 ListenSkt:=socket(pf_inet,sock_stream,0);
InternetAddr.sin_family:=af_inet;
InternetAddr.sin_addr.S_addr:=htonl(inaddr_any);
InternetAddr.sin_port:=htons(5150); bind(ListenSkt,@InternetAddr,SizeOf(InternetAddr)); NewEvent:=WSACreateEvent();//这里出错,提示Access violation at address 00000000.Read of address 00000000. WSAEventSelect(ListenSkt,NewEvent,fd_accept or fd_close); listen(ListenSkt,5);
SocketArray[EventTotal]:=ListenSkt;
EventArray[EventTotal]:=NewEvent; while True do
begin
//等候所有套接字上的网络事件
Index:=WSAWaitForMultipleEvents(EventTotal,@EventArray,False,wsa_infinite,False);
Index:=index-wsa_wait_event_0; //遍历所有事件,查看被传信的事件是否多于一个
for i:=index to EventTotal-1 do
begin
Index:=WSAWaitForMultipleEvents(1,@(EventArray[i]),True,1000,False);
if (index=WSA_Wait_Failed) or (index=WSA_wait_timeout) then
Continue
else begin
Index:=i;
WSAEnumNetworkEvents(SocketArray[index],EventArray[index],@NetWorkEvents); //检查FD_Accept消息
if (NetWorkEvents.lNetworkEvents and fd_accept)<>0 then
begin
if NetWorkEvents.iErrorCode[FD_Accept_bit]<>0 then
begin
Memo1.Lines.Add('FD_Accept failed with error '+IntToStr(NetWorkEvents.iErrorCode[fd_accept_bit]));
Break;
end; //接受一个新连接,并将它添加到套接字及事件列表中
AcceptSkt:=accept(Socketarray[index],nil,nil); //无法处理多于WSA_MAXIMUM_WAIT_EVENTS数量的套接字,故关闭接受套接字
if EventTotal>=WSA_MAXIMUM_WAIT_EVENTS then
begin
Memo1.Lines.Add('Too ManyConnections');
closesocket(AcceptSkt);
Break;
end; NewEvent:=WSACreateEvent(); WSAEventSelect(AcceptSkt,NewEvent,fd_read or fd_write or fd_close); Inc(EventTotal);
EventArray[EventTotal]:=NewEvent;
SocketArray[EventTotal]:=AcceptSkt;
//原文在这里Inc(EventTotal),我觉得应该写到前两行去
Memo1.Lines.Add('Socket '+IntToStr(AcceptSkt)+' Connected!');
end; //处理FD_Read通知
if (NetWorkEvents.lNetworkEvents and FD_read)<>0 then
begin
if (NetWorkEvents.iErrorCode[FD_read_Bit]<>0) then
begin
Memo1.Lines.Add('FD_read failed with error '+IntToStr(NetWorkEvents.iErrorCode[fd_read_bit]));
Break;
end;
//从套接字读入数据
ZeroMemory(buffer,SizeOf(buffer));
recv(socketarray[index-wsa_wait_event_0],buffer,SizeOf(buffer),0);
Memo1.Lines.Add('Socket ['+IntToStr(socketarray[index-wsa_wait_event_0])+'] Recv:'+buffer);
end; //处理FD_WRITE通知
if (NetWorkEvents.lNetworkEvents and FD_Write)<>0 then
begin
if NetWorkEvents.iErrorCode[fd_write_bit]<>0 then
begin
Memo1.Lines.Add('FD_Write failed with error '+IntToStr(NetWorkEvents.iErrorCode[fd_write_bit]));
break;
end;
send(SocketArray[index-wsa_wait_event_0],buffer,SizeOf(buffer),0);
Memo1.Lines.Add('Socket ['+IntToStr(Socketarray[index])+'] Send something...');
end; if (NetWorkEvents.lNetworkEvents and FD_Close)<>0 then
begin
if NetWorkEvents.iErrorCode[FD_close_bit]<>0 then
begin
Memo1.Lines.Add('FD_Close failed with error '+Inttostr(NetWorkEvents.iErrorCode[FD_close_bit]));
Break;
end;
closesocket(Socketarray[index]);
Memo1.Lines.Add('Socket ['+IntToStr(Socketarray[index])+'] Close !'); //从Socket和Event数组删除套接字与其关联的事件,并递减EventTotal
CompressArrays(EventArray,SocketArray,EventTotal,index);
end;
end;
end;
end;
FreeMem(buffer);
Memo1.Lines.Add('Server Exit!')
end;end.------------------------------
窗体上只有一个Memo1组件和一个Button1启动按钮,大家可以直接拷贝代码调试。执行到NewEvent:=WSACreateEvent();时提示错误:Access violation at address 00000000.Read of address 00000000.看了一些帖子,提示可能是内存未分配导致的,不过自己不知道要怎么改。
也有帖子写有好像需要手动加载WS2_32.dll,不过也试过,好像不行。
不知道有没有朋友遇到过类似问题,怎么解决的,指点一下。
环境:Delphi7+Indy9+XP,代码使用的I/O模型是WSAventSelect模型。
解决方案 »
- DBGridEh页脚汇总取整问题
- 有哪位兄弟对EDI(电子商务数据交换)标准有所了解的吗?可能的话是否可以提供一些相关文档给我.
- 500分求拦截数据的方法!
- dbgrid怎么才能在输入的时候降焦点锁定此行 不允许键盘鼠标向其他行移动
- 高分请版主!
- 怎样将字符串中的某几个字符删除?
- Delphi中有關文件屬性的操作!!
- 动态生成adoquery需要设哪些属性?立即给分
- 难到就没人解决吗?怎么把Excel中sheet1中的表复制到sheet2中吗?见帖 关于Excel表格复制的问题??
- 请问怎样在TStringlist中删除某个字符串?
- 欲哭无泪中,sybase12.52+ado
- 急:算法高手请进。有一个难题求解?
书上是P113页那段,我适当增加了一些信息输出的地方,用于方便调试。
------------------------------------
unit Unit1;interfaceuses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs,JwaWinsock2,StdCtrls;type
TForm1 = class(TForm)
Memo1: TMemo;
Button1: TButton;
Button2: TButton;
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
procedure FormClose(Sender: TObject; var Action: TCloseAction);
private
{ Private declarations }
public
SocketArray:array[0..WSA_MAXIMUM_WAIT_EVENTS-1] of TSocket;
EventArray:array[0..WSA_MAXIMUM_WAIT_EVENTS-1] of WSAEVENT;
NewEvent:wsaevent;
NetWorkEvents:TWSANetworkEvents;
InternetAddr:TSockAddrIn;
AcceptSkt,ListenSkt:TSocket;
EventTotal:DWORD;
index:DWORD;
Working:Boolean;
{ Public declarations }
end;var
Form1: TForm1;implementationprocedure CompressArrays(var pEventArray:array of wsaevent;pSocketArray:array of TSocket;var nEventTotal:DWORD;const nIndex:Integer);
var
i:integer;
begin
for i:=nIndex to Length(pEventArray)-2 do
begin
pEventArray[i]:=pEventArray[i+1];
pSocketArray[i]:=pSocketArray[i+1];
end;
pEventArray[Length(pEventArray)-1]:=0;
pSocketArray[Length(pEventArray)-1]:=0;
Dec(nEventTotal);
end;{$R *.dfm}procedure TForm1.FormCreate(Sender: TObject);
var
WSAData:TWSADATA;
begin
//1.初始化 WinSock
if (WSAStartup(MakeWord(2,0),WSAData)<>0) then
begin
//初始化失败
Memo1.Lines.Add('Winsock Init Failed');
Exit;
end
else
Memo1.Lines.Add('Socket initialize OK!');
end;procedure TForm1.FormDestroy(Sender: TObject);
begin
WSACleanup;
end;procedure TForm1.Button1Click(Sender: TObject);
var
i:DWORD;
buffer:PChar;
Re:Integer;
begin
Working:=True;
EventTotal:=0;
NewEvent:=0;
GetMem(buffer,1024);
ZeroMemory(buffer,1024); ListenSkt:=socket(PF_INET,SOCK_STREAM,0);
InternetAddr.sin_family:=AF_INET;
InternetAddr.sin_addr.S_addr:=htonl(INADDR_ANY);
InternetAddr.sin_port:=htons(8888); Re:=bind(ListenSkt,@InternetAddr,SizeOf(InternetAddr));
if Re=SOCKET_ERROR then
begin
Memo1.Lines.Add('Socket Bind Error ');
end else
Memo1.Lines.Add('Socket Bind OK '); NewEvent:=WSACreateEvent(); WSAEventSelect(ListenSkt,NewEvent,FD_ACCEPT or FD_CLOSE); listen(ListenSkt,5);
SocketArray[EventTotal]:=ListenSkt;
EventArray[EventTotal]:=NewEvent;
Inc(EventTotal); while Working do
begin
Application.ProcessMessages;
//等候所有套接字上的网络事件
Index:=WSAWaitForMultipleEvents(EventTotal,@EventArray,False,1000,False);
Index:=index-WSA_WAIT_EVENT_0;
Memo1.Lines.Add('Index='+IntToStr(index)+';WSA_WAIT_EVENT_0='+IntToStr(WSA_WAIT_EVENT_0)); //遍历所有事件,查看被传信的事件是否多于一个
for i:=index to EventTotal-1 do
begin
Index:=WSAWaitForMultipleEvents(1,@(EventArray[i]),True,1000,False);
if (index=WSA_WAIT_FAILED) or (index=WSA_WAIT_TIMEOUT) then
Continue
else begin
Index:=i;
WSAEnumNetworkEvents(SocketArray[index],EventArray[index],@NetWorkEvents); //检查FD_Accept消息
if (NetWorkEvents.lNetworkEvents and FD_ACCEPT)=FD_ACCEPT then
begin
if NetWorkEvents.iErrorCode[FD_ACCEPT_BIT]<>0 then
begin
Memo1.Lines.Add('FD_ACCEPT failed with error '+IntToStr(NetWorkEvents.iErrorCode[FD_ACCEPT_BIT]));
Break;
end; //接受一个新连接,并将它添加到套接字及事件列表中
AcceptSkt:=accept(SocketArray[index],nil,nil); //无法处理多于WSA_MAXIMUM_WAIT_EVENTS数量的套接字,故关闭接受套接字
if EventTotal>=WSA_MAXIMUM_WAIT_EVENTS then
begin
Memo1.Lines.Add('Too ManyConnections');
closesocket(AcceptSkt);
Break;
end; NewEvent:=WSACreateEvent(); WSAEventSelect(AcceptSkt,NewEvent,FD_READ or FD_WRITE or FD_CLOSE); EventArray[EventTotal]:=NewEvent;
SocketArray[EventTotal]:=AcceptSkt;
Inc(EventTotal);
Memo1.Lines.Add('Socket '+IntToStr(AcceptSkt)+' Connected!');
end; //处理FD_Read通知
if (NetWorkEvents.lNetworkEvents and FD_READ)=FD_READ then
begin
if (NetWorkEvents.iErrorCode[FD_READ_BIT]<>0) then
begin
Memo1.Lines.Add('FD_read failed with error '+IntToStr(NetWorkEvents.iErrorCode[FD_READ_BIT]));
Break;
end;
Memo1.Lines.Add('Socket ['+IntToStr(SocketArray[index])+'] Read something...');
//从套接字读入数据
ZeroMemory(buffer,1024);
recv(socketarray[index-WSA_WAIT_EVENT_0],buffer^,1024,0);
Memo1.Lines.Add('Socket ['+IntToStr(SocketArray[index-WSA_WAIT_EVENT_0])+'] Recv:'+buffer);
end; //处理FD_WRITE通知
if (NetWorkEvents.lNetworkEvents and FD_WRITE)=FD_WRITE then
begin
if NetWorkEvents.iErrorCode[FD_WRITE_BIT]<>0 then
begin
Memo1.Lines.Add('FD_Write failed with error '+IntToStr(NetWorkEvents.iErrorCode[FD_WRITE_BIT]));
break;
end;
send(SocketArray[index-WSA_WAIT_EVENT_0],buffer^,1024,0);
Memo1.Lines.Add('Socket ['+IntToStr(SocketArray[index])+'] Send something...');
end; //处理FD_CLOSE通知
if (NetWorkEvents.lNetworkEvents and FD_CLOSE)=FD_CLOSE then
begin
if NetWorkEvents.iErrorCode[FD_CLOSE_BIT]<>0 then
begin
Memo1.Lines.Add('FD_Close failed with error '+Inttostr(NetWorkEvents.iErrorCode[FD_CLOSE_BIT]));
closesocket(SocketArray[index]);
Memo1.Lines.Add('Socket ['+IntToStr(SocketArray[index])+'] Close !');
CompressArrays(EventArray,SocketArray,EventTotal,index);
Break;
end;
closesocket(SocketArray[index]);
Memo1.Lines.Add('Socket ['+IntToStr(SocketArray[index])+'] Close !'); //从Socket和Event数组删除套接字与其关联的事件,并递减EventTotal
CompressArrays(EventArray,SocketArray,EventTotal,index);
end;
end;
end;
end;
FreeMem(buffer);
Memo1.Lines.Add('Server Exit!')
end;procedure TForm1.Button2Click(Sender: TObject);
begin
Working:=False;
end;procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
Working:=False;
end;end.