TCP通訊過程介紹
首先介紹一下socket通訊的基本過程:這裡先如果有兩個傢伙在通訊,一個是S。還有一個叫C
(1)S開啟port監聽本地的port看看有沒有人來連線;
(2)與此同一時候C試圖去連線遠端的S。連線的地址就是S的地址加上S監聽的port號;
(3)S收到C的請求之後,建立連線,兩方共同持有連線的通道。可互相傳送/接收資料隨意次。此時S和C無差別。
(4)當中一方斷開連線,或者由於網路原因中斷連線,還有一方也會關閉;
(5)此時通訊過程結束;
整個步驟例如以下圖所看到的
普通ACE通訊類ACE_SOCK_*通訊過程
ACE_SOCK_Connector ACE_SOCK_Stream ACE_SOCK_Acceptor完畢上面的通訊過程:
TimerServer Edition 1.0 單次傳送
兩方建立連線》互發資料》關閉連線
Client:傳送自己的簽名給Server之後就準備接受Server發來的時間
Server:在連線建立後列印對方發來的簽名。之後回覆自己的時間給對方
Server 端 time_server_main.cpp
#include <ace/OS.h>
#include <ace/ACE.h>
#include <ace/Log_Msg.h>
#include <ace/SOCK_Acceptor.h>
#include "ace/Date_Time.h"
int main(int argc, char *argv[])
{
ACE_INET_Addr addr(1500);
ACE_SOCK_Acceptor server;
ACE_SOCK_Stream stream;
//啟動監聽
if(server.open(addr)==-1)
{
ACE_DEBUG ((LM_DEBUG,ACE_TEXT ("Server啟動監聽本地埠1500失敗\n")));
return 1;
}
else
{
ACE_DEBUG ((LM_DEBUG,ACE_TEXT ("Server啟動監聽本地埠1500成功\n")));
}
char msg[1000];
//建立連結
if(server.accept(stream)!=-1)
{
ACE_INET_Addr raddr;
stream.get_remote_addr(raddr);
ACE_DEBUG ((LM_DEBUG,ACE_TEXT ("Server建立連結成功 %s %d\n"),raddr.get_host_addr(),raddr.get_port_number()));
if(stream.recv(msg,sizeof(msg)-1)==-1) // just call socket recv
ACE_DEBUG ((LM_DEBUG,ACE_TEXT ("Server recv failed\n")));
else
{
ACE_DEBUG ((LM_DEBUG,ACE_TEXT ("Server recv : %s\n"),msg));
//get current time
ACE_Date_Time date;
sprintf(msg,"%ld-%ld-%ld %02ld:%02ld:%02ld:%02ld",date.year(),date.month(),date.day(),date.hour(),date.minute(),date.second(),date.microsec());
//傳送資料
stream.send_n(msg,sizeof(msg));
ACE_DEBUG ((LM_DEBUG,ACE_TEXT ("傳送當前時間%s至 %s %d\n"),msg,raddr.get_host_addr(),raddr.get_port_number()));
}
}
else
{
ACE_DEBUG ((LM_DEBUG,ACE_TEXT ("Server建立連結失敗\n")));
}
//關閉連結
stream.close();
ACE_DEBUG ((LM_DEBUG,ACE_TEXT ("Server連結關閉了\n")));
server.close();
return 0;
}
Client端time_client_main.cpp
#include "ace/OS.h"
#include <ace/OS_main.h>
#include <ace/ACE.h>
#include <ace/Log_Msg.h>
#include <ace/SOCK_Connector.h>
int main(int argc, char *argv[])
{
ACE_INET_Addr addr(1500,"127.0.0.1"); //remote address
ACE_SOCK_Connector con; // connetor for socket client
ACE_SOCK_Stream stream; // stream is for socket read/write
//建立連結
if(con.connect(stream,addr)==-1) //connect to remote address
{
ACE_DEBUG ((LM_DEBUG,ACE_TEXT ("Client建立連結失敗\n")));
return 1;
}
else
{
ACE_DEBUG ((LM_DEBUG,ACE_TEXT ("Client建立連結成功\n")));
}
const char msg[] = "Hello,ACE!";
//傳送資料
stream.send_n(msg,sizeof(msg)); // send_n function send exactly n bytes
char buffer[1024] = {0};
//接收資料
if(stream.recv(buffer,sizeof(buffer)-1)==-1) // just call socket recv
{
ACE_DEBUG ((LM_DEBUG,ACE_TEXT ("Client recv failed\n")));
return 1;
}
else
{
ACE_DEBUG ((LM_DEBUG,ACE_TEXT ("Client recv:%s\n"),buffer));
}
//斷開連結
if (stream.close () == -1) //close the connection
{
ACE_ERROR ((LM_ERROR,ACE_TEXT ("Client close failed\n")));
return 1;
}
else
{
ACE_ERROR ((LM_ERROR,ACE_TEXT ("Client close successed\n")));
}
return 0;
}
輸出:
TimerServer Edition 2.0 多次傳送
兩方建立連線》互發資料》關閉連線
(1)Client:傳送自己的簽名給Server之後就準備接受Server發來的時間,此過程反覆三次
(2)Server:在連線建立後列印對方發來的簽名。之後回覆自己的時間給對方。此過程直到對方關閉連結
Server 端 time_server_main.cpp
#include <ace/OS.h>
#include <ace/ACE.h>
#include <ace/Log_Msg.h>
#include <ace/SOCK_Acceptor.h>
#include "ace/Date_Time.h"
int main(int argc, char *argv[])
{
ACE_INET_Addr addr(1500);
ACE_SOCK_Acceptor server;
ACE_SOCK_Stream stream;
//啟動監聽
if(server.open(addr)==-1)
{
ACE_DEBUG ((LM_DEBUG,ACE_TEXT ("Server啟動監聽本地埠1500失敗\n")));
return 1;
}
else
{
ACE_DEBUG ((LM_DEBUG,ACE_TEXT ("Server啟動監聽本地埠1500成功\n")));
}
char msg[1000];
//建立連結
if(server.accept(stream)!=-1)
{
ACE_INET_Addr raddr;
stream.get_remote_addr(raddr);
ACE_DEBUG ((LM_DEBUG,ACE_TEXT ("Server建立連結成功 %s %d\n"),raddr.get_host_addr(),raddr.get_port_number()));
while(stream.recv(msg,sizeof(msg)-1)!=-1) // just call socket recv
{
ACE_DEBUG ((LM_DEBUG,ACE_TEXT ("Server recv : %s\n"),msg));
//get current time
ACE_Date_Time date;
sprintf(msg,"%ld-%ld-%ld %02ld:%02ld:%02ld:%02ld",date.year(),date.month(),date.day(),date.hour(),date.minute(),date.second(),date.microsec());
//傳送資料
stream.send_n(msg,sizeof(msg));
ACE_DEBUG ((LM_DEBUG,ACE_TEXT ("傳送當前時間%s至 %s %d\n"),msg,raddr.get_host_addr(),raddr.get_port_number()));
ACE_OS::sleep(1);
}
}
else
{
ACE_DEBUG ((LM_DEBUG,ACE_TEXT ("Server建立連結失敗\n")));
}
//關閉連結
stream.close();
ACE_DEBUG ((LM_DEBUG,ACE_TEXT ("Server連結關閉了\n")));
server.close();
return 0;
}
Client端time_client_main.cpp
#include "ace/OS.h"
#include <ace/OS_main.h>
#include <ace/ACE.h>
#include <ace/Log_Msg.h>
#include <ace/SOCK_Connector.h>
int main(int argc, char *argv[])
{
ACE_INET_Addr addr(1500,"127.0.0.1"); //remote address
ACE_SOCK_Connector con; // connetor for socket client
ACE_SOCK_Stream stream; // stream is for socket read/write
//建立連結
if(con.connect(stream,addr)==-1) //connect to remote address
{
ACE_DEBUG ((LM_DEBUG,ACE_TEXT ("Client建立連結失敗\n")));
return 1;
}
else
{
ACE_DEBUG ((LM_DEBUG,ACE_TEXT ("Client建立連結成功\n")));
}
const char msg[] = "I'm Client ABC";
//傳送資料
int n=3;
for (int i=0; stream.send_n(msg,sizeof(msg)) != -1 && i<3;++i)
{
ACE_DEBUG ((LM_DEBUG,ACE_TEXT ("Client send successed\n")));
char buffer[1024] = {0};
//接收資料
if(stream.recv(buffer,sizeof(buffer)-1)==-1) // just call socket recv
{
ACE_DEBUG ((LM_DEBUG,ACE_TEXT ("Client recv failed\n")));
return 1;
}
else
{
ACE_DEBUG ((LM_DEBUG,ACE_TEXT ("Client recv:%s\n"),buffer));
}
ACE_OS::sleep(1);
}
//斷開連結
if (stream.close () == -1) //close the connection
{
ACE_ERROR ((LM_ERROR,ACE_TEXT ("Client close failed\n")));
return 1;
}
else
{
ACE_ERROR ((LM_ERROR,ACE_TEXT ("Client close successed\n")));
}
return 0;
}