WinSockAPI的问题(100分)

  • 主题发起人 chenge1980
  • 开始时间
C

chenge1980

Unregistered / Unconfirmed
GUEST, unregistred user!
用Connect连接到服务器后返回值是-1错误代码是10037 sckAlreadyComplete<br>应该如何解决???<br>
 
10037-WSAEALREADY(在指定的套接口上正在进行一个非阻塞的Connect)<br>
 
很奇怪,把WSAAsyncSelect()挪到connect后边又很正常了,只是没法触发connect事件了
 
我举个例子,希望能有所帮助:<br><br>{--------------------------------------------------------------<br>Simple Example.<br>Implement TCP(both Client and Server) with Socket API<br>&lt;zw84611@sina.com&gt;<br>--------------------------------------------------------------}<br><br>unit Unit1;<br><br>interface<br><br>uses<br>&nbsp; Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,<br>&nbsp; WinSock, StdCtrls;<br><br>const<br>&nbsp; WM_SOCK = WM_USER + 1; &nbsp; &nbsp;//自定义windows消息<br>&nbsp; TCP_PORT = 5432; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;//设定TCP端口号<br><br>type<br>&nbsp; TForm1 = class(TForm)<br>&nbsp; &nbsp; Button1: TButton;<br>&nbsp; &nbsp; Edit1: TEdit;<br>&nbsp; &nbsp; ListBox1: TListBox;<br>&nbsp; &nbsp; procedure Button1Click(Sender: TObject);<br>&nbsp; &nbsp; procedure FormClose(Sender: TObject; var Action: TCloseAction);<br>&nbsp; &nbsp; procedure FormCreate(Sender: TObject);<br>&nbsp; private<br>&nbsp; &nbsp; { Private declarations }<br>&nbsp; &nbsp; HasConnected, IsServer: boolean;<br>&nbsp; &nbsp; CliSocket, SvrSocket: integer;<br>&nbsp; &nbsp; SvrAddrIn, CliAddrIn:TSockAddrIn;<br>&nbsp; &nbsp; procedure InitSocket;<br>&nbsp; &nbsp; procedure SendData(Content: string);<br>&nbsp; &nbsp; procedure ReadData(var Message: TMessage); message WM_SOCK;<br>&nbsp; &nbsp; procedure SockConnect;<br>&nbsp; public<br>&nbsp; &nbsp; { Public declarations }<br>&nbsp; end;<br><br>var<br>&nbsp; Form1: TForm1;<br><br>implementation<br><br>{$R *.DFM}<br><br>procedure TForm1.InitSocket;<br>var<br>&nbsp; wsadata: TWsadata;<br>&nbsp; err{, optval}: integer;<br>begin<br><br>&nbsp; WSAStartup($0101,WSAData);<br>&nbsp; <br>&nbsp; CliSocket := socket(AF_INET, SOCK_STREAM,IPPROTO_IP);<br>&nbsp; SvrSocket := socket(AF_INET, SOCK_STREAM,IPPROTO_IP);<br><br>&nbsp; if (CliSocket = INVALID_SOCKET)or(SvrSocket = INVALID_SOCKET) then<br>&nbsp; begin<br>&nbsp; &nbsp; ShowMessage(inttostr(WSAGetLastError())+' &nbsp;Socket创建失败');<br>&nbsp; &nbsp; CloseSocket(CliSocket);<br>&nbsp; &nbsp; exit;<br>&nbsp; end;<br><br>&nbsp; SvrAddrIn.sin_addr.s_addr:= INADDR_ANY;<br>&nbsp; SvrAddrIn.sin_family := AF_INET;<br>&nbsp; SvrAddrIn.sin_port :=htons(TCP_PORT);<br>&nbsp; Bind(SvrSocket, SvrAddrIn, sizeof(SvrAddrIn));<br><br>&nbsp; err := Listen(SvrSocket,5);<br>&nbsp; if err&lt;&gt;0 then ShowMessage('Listen error.');<br><br>&nbsp; {optval := 1;<br>&nbsp; if SetSockopt(SvrSocket,SOL_SOCKET,SO_REUSEADDR,pchar(@optval),sizeof(optval)) = SOCKET_ERROR then<br>&nbsp; begin<br>&nbsp; &nbsp; showmessage('SO_REUSEADDR set error.');<br>&nbsp; end; }<br><br>&nbsp; //绑定消息映射<br>&nbsp; WSAAsyncSelect(SvrSocket, Handle , WM_SOCK, FD_READ or FD_ACCEPT or FD_CONNECT or FD_WRITE or FD_CLOSE);<br>&nbsp; WSAAsyncSelect(CliSocket, Handle , WM_SOCK, FD_READ or FD_ACCEPT or FD_CONNECT or FD_WRITE or FD_CLOSE);<br><br>end;<br><br>procedure TForm1.SockConnect;<br>var<br>&nbsp; err: integer;<br>begin<br><br>&nbsp; CliAddrIn.sin_addr.s_addr:=inet_addr(PChar(Edit1.Text));<br>&nbsp; CliAddrIn.sin_family := AF_INET;<br>&nbsp; CliAddrIn.sin_port :=htons(TCP_PORT);<br>&nbsp; repeat<br>&nbsp; &nbsp; err:=connect(CliSocket,CliAddrIn, SizeOf(CliAddrIn));<br>&nbsp; &nbsp; if err = -1 then<br>&nbsp; &nbsp; begin<br>&nbsp; &nbsp; &nbsp; { &nbsp;if we use WSAAsyncSelect(CliSocket...) in order to receive data at<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Client side, here will get error, but it still works. why?<br>&nbsp; &nbsp; &nbsp; }<br>&nbsp; &nbsp; &nbsp; //ShowMessage('connect error.');<br>&nbsp; &nbsp; &nbsp; //ListBox1.Items.Add('connect error.');<br>&nbsp; &nbsp; &nbsp; HasConnected := false;<br>&nbsp; &nbsp; &nbsp; break;<br>&nbsp; &nbsp; end<br>&nbsp; &nbsp; else<br>&nbsp; &nbsp; begin<br>&nbsp; &nbsp; &nbsp; HasConnected := true;<br>&nbsp; &nbsp; &nbsp; IsServer := false;<br>&nbsp; &nbsp; end;<br>&nbsp; until err=0;<br><br>end;<br><br>procedure TForm1.SendData(Content: string);<br>begin<br>&nbsp; &nbsp; Send(CliSocket,Content[1],length(Content),0);<br>end;<br><br>procedure TForm1.ReadData(var Message: TMessage);<br>var<br>&nbsp; Event: word;<br>&nbsp; Buf:array[0..1023] of char;<br>&nbsp; AddrLen, DataLen: integer;<br>begin<br>&nbsp; //<br>&nbsp; AddrLen := &nbsp;sizeof(SvrAddrIn);<br>&nbsp; Event := WSAGetSelectEvent(Message.LParam);<br><br>&nbsp; case Event of<br>&nbsp; &nbsp; FD_CONNECT:<br>&nbsp; &nbsp; begin<br>&nbsp; &nbsp; &nbsp; ListBox1.Items.Add('connect');<br>&nbsp; &nbsp; &nbsp; HasConnected := true;<br>&nbsp; &nbsp; &nbsp; //do nothing?<br>&nbsp; &nbsp; end;<br>&nbsp; &nbsp; FD_ACCEPT:<br>&nbsp; &nbsp; begin<br>&nbsp; &nbsp; &nbsp; IsServer := true;<br>&nbsp; &nbsp; &nbsp; HasConnected := true;<br>&nbsp; &nbsp; &nbsp; ListBox1.Items.Add('accept');<br>&nbsp; &nbsp; &nbsp; //CloseSocket(CliSocket);<br>&nbsp; &nbsp; &nbsp; CliSocket := Accept(SvrSocket,@SvrAddrIn,@AddrLen);<br>&nbsp; &nbsp; end;<br>&nbsp; &nbsp; FD_READ:<br>&nbsp; &nbsp; begin<br>&nbsp; &nbsp; &nbsp; DataLen := Recv(CliSocket,Buf,1024,0);<br>&nbsp; &nbsp; &nbsp; buf[DataLen] := #0;<br>&nbsp; &nbsp; &nbsp; ListBox1.Items.Add(Buf);<br>&nbsp; &nbsp; end;<br>&nbsp; &nbsp; FD_WRITE:<br>&nbsp; &nbsp; begin<br>&nbsp; &nbsp; &nbsp; ListBox1.Items.Add('write');<br>&nbsp; &nbsp; end;<br>&nbsp; &nbsp; FD_OOB:<br>&nbsp; &nbsp; begin<br>&nbsp; &nbsp; &nbsp; ListBox1.Items.Add('FD_OOB');<br>&nbsp; &nbsp; end;<br>&nbsp; &nbsp; FD_CLOSE:<br>&nbsp; &nbsp; begin<br>&nbsp; &nbsp; &nbsp; HasConnected := false;<br>&nbsp; &nbsp; &nbsp; ListBox1.Items.Add('close');<br>&nbsp; &nbsp; end;<br>&nbsp; end; //end of case<br>end;<br><br>procedure TForm1.Button1Click(Sender: TObject);<br>begin<br>&nbsp; //202.104.32.230<br>&nbsp; if (not IsServer)and(not HasConnected) then SockConnect;<br>&nbsp; SendData('hello, world');<br>end;<br><br>procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);<br>begin<br>&nbsp; CloseSocket(SvrSocket);<br>&nbsp; CloseSocket(CliSocket);<br>end;<br><br>procedure TForm1.FormCreate(Sender: TObject);<br>begin<br>&nbsp; HasConnected := false;<br>&nbsp; IsServer := false;<br>&nbsp; InitSocket;<br>end;<br><br>end.<br><br><br>//源程序:http://www.playicq.com/dispdoc.php?t=27&amp;id=2148<br>
 
不大明白 &nbsp;<br>&nbsp; &nbsp;repeat<br>&nbsp; &nbsp; err:=connect(CliSocket,CliAddrIn, SizeOf(CliAddrIn));<br>&nbsp; &nbsp; if err = -1 then<br>&nbsp; &nbsp; begin<br>&nbsp; &nbsp; &nbsp; { &nbsp;if we use WSAAsyncSelect(CliSocket...) in order to receive data at<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Client side, here will get error, but it still works. why?<br>&nbsp; &nbsp; &nbsp; }<br>&nbsp; &nbsp; &nbsp; //ShowMessage('connect error.');<br>&nbsp; &nbsp; &nbsp; //ListBox1.Items.Add('connect error.');<br>&nbsp; &nbsp; &nbsp; HasConnected := false;<br>&nbsp; &nbsp; &nbsp; break;<br>&nbsp; &nbsp; end<br>&nbsp; &nbsp; else<br>&nbsp; &nbsp; begin<br>&nbsp; &nbsp; &nbsp; HasConnected := true;<br>&nbsp; &nbsp; &nbsp; IsServer := false;<br>&nbsp; &nbsp; end;<br>&nbsp; until err=0;<br>为什么要这样做,而且这样触发conncet时,其实并未连接,真正连接成功时err的值也是-1
 
不,是连接了<br>err:=connect(CliSocket,CliAddrIn, SizeOf(CliAddrIn));一句就已经连接了。<br><br>之所以这样,是因为我的Client和Server做在一个程序里,出现了这个问题(我不太明白<br>为什么)其实你把Client和Server分开,<br>或把<br>WSAAsyncSelect(CliSocket, Handle , WM_SOCK, FD_READ or FD_ACCEPT or FD_CONNECT or FD_WRITE or FD_CLOSE);<br>这一句去掉,只留<br>WSAAsyncSelect(SvrSocket, Handle , WM_SOCK, FD_READ or FD_ACCEPT or FD_CONNECT or FD_WRITE or FD_CLOSE);<br>则上面的代码不必注释掉,一点问题都不会有。
 
我试过了,我只用一个Client,只要WSAAsyncSelect在connect前面,err的值永远是-1
 
仅一个Client是不需要WSAAsyncSelect的
 
我是在工作线程里用的,不调用WSAAsyncSelect无法触发事件
 
基本搞定
 
顶部