clientsocket 阻塞到底怎么接收和发送数据!

zahlink 2003-10-14 11:12:39
是用线程吗?给个简单的例子吧
...全文
197 7 打赏 收藏 转发到动态 举报
写回复
用AI写文章
7 条回复
切换为时间正序
请发表友善的回复…
发表回复
zahlink 2003-10-14
  • 打赏
  • 举报
回复
TtestsendThread = class(TThread)
private
FQuery: TADoQuery; { 线程中的查询组件 }
FSocket:TClientSocket;
protected
procedure Execute;override;
public
constructor Create(CreateSuspended: Boolean); virtual; { 线程构造器 }
end;
TtestreadThread = class(TThread)
private
FSocket:TClientSocket;
protected
procedure Execute;override;
public
constructor Create(CreateSuspended: Boolean); virtual; { 线程构造器 }
end;
constructor TtestsendThread.Create(CreateSuspended: Boolean);
begin
inherited Create(CreateSuspended);
self.FreeOnTerminate:=true;
FSocket:=TClientSocket.Create(Application);
FSocket.Host:='127.0.0.1';
FSocket.Port:=8801;
PSocket.clienttype:=ctBlocking;
FQuery:=TADOQuery.Create(Application);
Fquery.ConnectionString:='Provider=SQLOLEDB.1;Persist Security Info=False;User ID=sa;Initial Catalog=mybase;Data Source=zhangaihua';
end;

constructor TtestreadThread.Create(CreateSuspended: Boolean);
begin
inherited Create(CreateSuspended);
self.FreeOnTerminate:=true;
FSocket:=TClientSocket.Create(Application);
FSocket.Host:='127.0.0.1';
FSocket.Port:=8801;
PSocket.clienttype:=ctBlocking;
end;

procedure TtestsendThread.Execute;
begin
if WaitForSingleObject(hMutex,INFINITE)=WAIT_OBJECT_0 then
begin
try
FSocket.Active:=true;
if Fsocket.Active then
begin
CoInitialize(Nil);
FQuery.SQL.Clear;
FQuery.SQL.Add('select * from cmppwait');
FQuery.Open;
if FQuery.RecordCount>0 then
begin
FSocket.Socket.SendText('好好!');
end;
end;
finally
CoUninitialize;
end;
end;
ReleaseMutex(hMutex);
end;

procedure TtestreadThread.Execute;
begin
if WaitForSingleObject(hMutex,INFINITE)=WAIT_OBJECT_0 then
begin
FSocket.Active:=true;
if Fsocket.Active then
begin
showmessage(Fsocket.Socket.ReceiveText);
end;
end;
ReleaseMutex(hMutex);
end;
这个是我写的东西!我也不知道到底该怎么写!反正是阻塞的这边写的时候那边不会发送东西的!但是我写的东西和我的服务端连不上,帮我看看吧是什么问题!
halfdream 2003-10-14
  • 打赏
  • 举报
回复
呵呵。。这种用异步的非阻塞方式容易处理些。
用阻塞方式,多半得使用一个工作线程主动的读它。。
outer2000 2003-10-14
  • 打赏
  • 举报
回复
唉;
线程里有个循环看到了没有?
一般来说这个循环总是在运行的;等SERVER的消息;或者发自己的消息;
自己看看吧
zahlink 2003-10-14
  • 打赏
  • 举报
回复
不行啊,现在是连在服务端上,服务端可能在任何时候发过来信息!我自己这端也是如果库里有东西就发送!如果不用线程怎么办呢!肯定要不断的查看端口有没有过来的信息吧
outer2000 2003-10-14
  • 打赏
  • 举报
回复
from delphi help;
outer2000 2003-10-14
  • 打赏
  • 举报
回复
This example shows the execute method of a thread used to send requests to a server over a socket connection:

procedure TMyClientThread.Execute;

var
TheStream: TWinSocketStream;
buffer: string;
begin
{ create a TWinSocketStream for reading and writing }
TheStream := TWinSocketStream.Create(ClientSocket1.Socket, 60000);
try
{ fetch and process commands until the connection or thread is terminated }
while (not Terminated) and (ClientSocket1.Active) do
begin
try
GetNextRequest(buffer); { GetNextRequest must be a thread-safe method }

{ write the request to the server }
TheStream.Write(buffer, Length(buffer) + 1);
{ continue the communication (eg read a response from the server) }
...
except
if not(ExceptObject is EAbort) then
Synchronize(HandleThreadException); { you must write HandleThreadException }
end;
end;
finally
TheStream.Free;
end;
end;
vargent77 2003-10-14
  • 打赏
  • 举报
回复
不需要线程。
发送可以用ClientSocket1.Socket.SendText(发的东西)
接收就是ClientSocket1.Socket.ReceiveText(接受的内容)
组赛就用ClientSocket1.Socket.clienttype:=ctBlocking;
就行了
本程序,实现一个简单的语音聊天功能,将麦克风采集到的音频数据经G711压缩后,通过UDP协议传输。在本文中 不讨论如何通过麦克风采集音频数据,也不讨论G711压缩的细节,相关内容可以查看文章后参考文献的内容。 系统架构如下所示: | Invite | | --------------------------------> | | OK | | <-------------------------------- | | | | --------------------------------> | | Audio flow | | <-------------------------------- | | Bye | | --------------------------------> | A B 系统所用到的命令如:Invite、OK、Bye等设计为一个枚举类型变量, enum Command { Invite, //Make a call. Bye, //End a call. Busy, //User busy. OK, //Response to an invite message. OK is sent to //indicate that call is accepted. Null, //No command. } 当用户想要语音聊天时,发送Invite消息,等待对方的反馈OK应答。当收到OK应答后,开始发送/接受 语音信息。如果对方拒绝聊天,则发送Busy信息作为应答。要终止聊天时,发送Bye消息即可。 程序在端口1450同步实现连接建立消息的收发,在端口1550异步收发聊天信息。也就是说,本程序监听 两个端口,一个负责呼叫消息,另一个负责音频数据。 监听1450端口的代码: //使用UDP clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); EndPoint ourEP = new IPEndPoint(IPAddress.Any, 1450); //Listen asynchronously on port 1450 for //coming messages (Invite, Bye, etc). clientSocket.Bind(ourEP); //Receive data from any IP. EndPoint remoteEP = (EndPoint)(new IPEndPoint(IPAddress.Any, 0)); byteData = new byte[1024]; //Receive data asynchornously. clientSocket.BeginReceiveFrom(byteData, 0, byteData.Length, SocketFlags.None, ref remoteEP, new AsyncCallback(OnReceive), null); 当收到发送来的消息后,根据消息类型来进行对应的处理。 private void OnReceive(IAsyncResult ar) { try { EndPoint receivedFromEP = new IPEndPoint(IPAddress.Any, 0); //Get the IP from where we got a message. clientSocket.EndReceiveFrom(ar, ref receivedFromEP); //Convert the bytes received into an object of type Data. Data msgReceived = new Data(byteData); //Act according to the received message. switch (msgReceived.cmdCommand) { //We have an incoming call. case Command.Invite: { if (bIsCallActive == false) { //We have no active call. //Ask the user to accept the call or not. if (MessageBox.Show("Call coming from " + msgReceived.strName + ".\r\n\r\nAccept it?", "VoiceChat", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes) { SendMessage(Command.OK, receivedFromEP); vocoder = msgReceived.vocoder; otherPartyEP = receivedFromEP; otherPartyIP = (IPEndPoint)receivedFromEP; InitializeCall(); } else { //The call is declined. Send a busy response. SendMessage(Command.Busy, receivedFromEP); } } else { //We already have an existing call. Send a busy response. SendMessage(Command.Busy, receivedFromEP); } break; } //OK is received in response to an Invite. case Command.OK: { //Start a call. InitializeCall(); break; } //Remote party is busy. case Command.Busy: { MessageBox.Show("User busy.", "VoiceChat", MessageBoxButtons.OK, MessageBoxIcon.Exclamation); break; } case Command.Bye: { //Check if the Bye command has indeed come from the user/IP with which we have //a call established. This is used to prevent other users from sending a Bye, which //would otherwise end the call. if (receivedFromEP.Equals (otherPartyEP) == true) { //End the call. UninitializeCall(); } break; } } byteData = new byte[1024]; //Get ready to receive more commands. clientSocket.BeginReceiveFrom(byteData, 0, byteData.Length, SocketFlags.None, ref receivedFromEP, new AsyncCallback (OnReceive), null); } catch (Exception ex) { MessageBox.Show(ex.Message, "VoiceChat-OnReceive ()", MessageBoxButtons.OK, MessageBoxIcon.Error); } } 为了保证在收发音频数据时,不产生UI阻塞,采用多线程来异步收发数据。 private void InitializeCall() { try { //Start listening on port 1500. udpClient = new UdpClient(1550); Thread senderThread = new Thread(new ThreadStart(Send)); Thread receiverThread = new Thread(new ThreadStart(Receive)); bIsCallActive = true; //Start the receiver and sender thread. receiverThread.Start(); senderThread.Start(); btnCall.Enabled = false; btnEndCall.Enabled = true; } catch (Exception ex) { MessageBox.Show(ex.Message, "VoiceChat-InitializeCall ()", MessageBoxButtons.OK, MessageBoxIcon.Error); } } 异步发送从麦克风采集到的音频数据 * Send synchronously sends data captured from microphone across the network on port 1550. */ private void Send() { try { //The following lines get audio from microphone and then send them //across network. captureBuffer = new CaptureBuffer(captureBufferDescription, capture); CreateNotifyPositions(); int halfBuffer = bufferSize / 2; captureBuffer.Start(true); bool readFirstBufferPart = true; int offset = 0; MemoryStream memStream = new MemoryStream(halfBuffer); bStop = false; while (!bStop) { autoResetEvent.WaitOne(); memStream.Seek(0, SeekOrigin.Begin); captureBuffer.Read(offset, memStream, halfBuffer, LockFlag.None); readFirstBufferPart = !readFirstBufferPart; offset = readFirstBufferPart ? 0 : halfBuffer; //TODO: Fix this ugly way of initializing differently. //Choose the vocoder. And then send the data to other party at port 1550. if (vocoder == Vocoder.ALaw) { byte[] dataToWrite = ALawEncoder.ALawEncode(memStream.GetBuffer()); udpClient.Send(dataToWrite, dataToWrite.Length, otherPartyIP.Address.ToString (), 1550); } else if (vocoder == Vocoder.uLaw) { byte[] dataToWrite = MuLawEncoder.MuLawEncode(memStream.GetBuffer()); udpClient.Send(dataToWrite, dataToWrite.Length, otherPartyIP.Address.ToString(), 1550); } else { byte[] dataToWrite = memStream.GetBuffer(); udpClient.Send(dataToWrite, dataToWrite.Length, otherPartyIP.Address.ToString(), 1550); } } } catch (Exception ex) { MessageBox.Show(ex.Message, "VoiceChat-Send ()", MessageBoxButtons.OK, MessageBoxIcon.Error); } finally { captureBuffer.Stop(); //Increment flag by one. nUdpClientFlag += 1; //When flag is two then it means we have got out of loops in Send and Receive. while (nUdpClientFlag != 2) { } //Clear the flag. nUdpClientFlag = 0; //Close the socket. udpClient.Close(); } } 从端口1550处接受收到的音频数据 private void Receive() { try { bStop = false; IPEndPoint remoteEP = new IPEndPoint(IPAddress.Any, 0); while (!bStop) { //Receive data. byte[] byteData = udpClient.Receive(ref remoteEP); //G711 compresses the data by 50%, so we allocate a buffer of double //the size to store the decompressed data. byte[] byteDecodedData = new byte[byteData.Length * 2]; //Decompress data using the proper vocoder. if (vocoder == Vocoder.ALaw) { ALawDecoder.ALawDecode(byteData, out byteDecodedData); } else if (vocoder == Vocoder.uLaw) { MuLawDecoder.MuLawDecode(byteData, out byteDecodedData); } else { byteDecodedData = new byte[byteData.Length]; byteDecodedData = byteData; } //Play the data received to the user. playbackBuffer = new SecondaryBuffer(playbackBufferDescription, devi

5,388

社区成员

发帖
与我相关
我的任务
社区描述
Delphi 开发及应用
社区管理员
  • VCL组件开发及应用社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧