Hjælp til WinSock programmering
Davs Eksperter! Jeg sidder og laver et lille serverprogram med Windows Sockets API, men nu er jeg stødt på et mærkelig problem.Her er kildekoden til mit program:
program Server;
uses
Forms, Windows, Messages, WinSock,
Exitcodes in \'Exitcodes.pas\';
const
WM_SERVER_SOCK_NOTIFY = WM_USER;
WM_CLIENT_SOCK_NOTIFY = WM_USER + 1;
var
WSAData: TWSAData;
ServerSocketID, ClientSocketID: Integer;
ServerAddr, ClientAddr: sockaddr_in;
AddrLen: Integer;
Connected: Boolean;
Zero: LongInt;
Msg: tagMSG;
procedure WSAFailure;
begin
case WSAGetLastError of
WSAENETDOWN: PostQuitMessage(EC_NET_DOWN);
WSAEAFNOSUPPORT: PostQuitMessage(EC_AF_NOT_SUPPORTED);
WSAEMFILE: PostQuitMessage(EC_OUT_OF_SOCKETS);
WSAENOBUFS: PostQuitMessage(EC_OUT_OF_BUF);
WSAEADDRINUSE: PostQuitMessage(EC_ADDR_IN_USE);
else
PostQuitMessage(EC_UNKNOWN_ERROR);
end;
end;
{$R *.RES}
begin
AddrLen := SizeOf(sockaddr_in);
Zero := 0;
// Initialize Windows Sockets 1.1
if WSAStartUp($0101, WSAData) <> 0 then
PostQuitMessage(EC_WSASTARTUP_FAILED)
else
begin
// Create socket
ServerSocketID := Socket(AF_INET, SOCK_STREAM, 0);
if ServerSocketID = INVALID_SOCKET then
WSAFailure
else
begin
// Bind socket
with ServerAddr do
begin
sin_family := AF_INET;
sin_port := 8445;
sin_addr.S_addr := INADDR_ANY;
FillChar(sin_zero, 8, 0);
end;
if Bind(ServerSocketID, ServerAddr, AddrLen) <> 0 then
WSAFailure
else
if WSAAsyncSelect(ServerSocketID, Application.Handle, WM_SERVER_SOCK_NOTIFY, FD_ACCEPT) <> 0 then
WSAFailure;
end;
end;
Connected := False;
// ********** MAIN MESSAGE LOOP **********
while GetMessage(Msg, Application.Handle, 0, $7FFF) do
begin
TranslateMessage(Msg);
case Msg.Message of
WM_SERVER_SOCK_NOTIFY: if not Connected then
begin
ClientSocketID := Accept(ServerSocketID, @ClientAddr, @AddrLen);
if ClientSocketID <> INVALID_SOCKET then
begin
WSAAsyncSelect(ClientSocketID, Application.Handle, WM_CLIENT_SOCK_NOTIFY, FD_READ or FD_CLOSE);
Connected := True;
end;
end;
WM_CLIENT_SOCK_NOTIFY: case WSAGetSelectEvent(Msg.lParam) of
FD_CLOSE: begin
CloseSocket(ClientSocketID);
Connected := False;
end;
FD_READ: begin
// Read data
end;
end;
WM_CLOSE: PostMessage(Application.Handle, WM_DESTROY, 0, 0);
WM_DESTROY: PostQuitMessage(EC_NO_ERROR);
end;
end;
// Close server socket
CloseSocket(ServerSocketID);
// Close Windows Sockets
WSACleanUp;
end.
unit Exitcodes;
interface
const
// Exit codes
EC_NO_ERROR = 0; // No error
EC_WSASTARTUP_FAILED = 1; // Windows Sockets Startup failed
EC_NET_DOWN = 2; // Network provider failed
EC_AF_NOT_SUPPORTED = 3; // Address family not supported
EC_OUT_OF_SOCKETS = 4; // Out of socket handles
EC_OUT_OF_BUF = 5; // Windows Sockets are out of buffer
EC_ADDR_IN_USE = 6; // Address and/or port is in use
EC_UNKNOWN_ERROR = 32767; // An unknown error occured
implementation
end.
Det, der er mærkeligt, er at programmet virker fint nok - den opretter en socket, lytter til en port, og returnerer ingen fejlkoder. Men den reagerer alligevel ikke på anmodninger om at oprette forbindelse til serveren.
Jeg tror at det er WSAAsyncSelect, der er noget i vejen med. Den får Windows til at sende messages, når der sker noget, der vedrører den angivede socket, som f.eks. anmodninger om forbindelse, eller modtagelse af data. Problemet er, at programmet aldrig modtager nogen messages fra Windows! Hvad er der i vejen?