国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學(xué)院 > 開發(fā)設(shè)計 > 正文

socket長鏈接與短連接

2019-11-08 01:54:49
字體:
供稿:網(wǎng)友

長鏈接------------------

心跳: socket模擬網(wǎng)頁的報文連接某個網(wǎng)站,創(chuàng)建tcp的socket后,當我socket.connect后,如果在5到7秒鐘不socket.send,那么這個鏈接就失效了。 請問如何長時間的保持這個鏈接 這是在服務(wù)器端的設(shè)置的,客戶端沒法設(shè)置,可以發(fā)送心跳包。 socket.connect后,每3-4秒用socket.send發(fā)送一字節(jié)數(shù)據(jù)(內(nèi)容隨便),然后觀查這個連接是否保持。 lientSocket=serverSocket.accept(); OutputStream os = clientSocket.getOutputStream();           ObjectOutputStream oos=new ObjectOutputStream(os); oos.writeObject(al); oos.flush(); oos.close()//socket會關(guān)閉 實現(xiàn): 長連接的維持,是要客戶端程序,定時向服務(wù)端程序,發(fā)送一個維持連接包的。 如果,長時間未發(fā)送維持連接包,服務(wù)端程序?qū)嚅_連接。 客戶端: 通過持有Client對象,可以隨時(使用sendObject方法)發(fā)送Object給服務(wù)端。 如果keepAliveDelay毫秒(程序中是2秒)內(nèi)未發(fā)送任何數(shù)據(jù),則,自動發(fā)送一個KeepAlive對象給服務(wù)端, 用于維持連接。 由于,我們向服務(wù)端,可以發(fā)送很多不同的對象,服務(wù)端也可以返回不同的對象。 所以,對于返回對象的處理,要編寫具體的ObjectAction實現(xiàn)類進行處理。 通過Client.addActionMap方法進行添加。這樣,程序會回調(diào)處理。 服務(wù)端: 由于客戶端會定時(keepAliveDelay毫秒)發(fā)送維持連接的信息過來,所以,服務(wù)端要有一個檢測機制。 即當服務(wù)端receiveTimeDelay毫秒(程序中是3秒)內(nèi)未接收任何數(shù)據(jù),則,自動斷開與客戶端的連接。 

長連接與短連接的操作過程 通常的短連接操作步驟是:   連接→數(shù)據(jù)傳輸→關(guān)閉連接;而長連接通常就是:   連接→數(shù)據(jù)傳輸→保持連接(心跳)→數(shù)據(jù)傳輸→保持連接(心跳)→……→關(guān)閉連接; 這就要求長連接在沒有數(shù)據(jù)通信時,定時發(fā)送數(shù)據(jù)包(心跳),以維持連接狀態(tài),短連接在沒有數(shù)據(jù)傳輸時直接關(guān)閉就行了什么時候用長連接,短連接?長連接多用于操作頻繁,點對點的通訊,而且連接數(shù)不能太多情況。每個TCP連接都需要三步握手,這需要時間,如果每個操作都是先連接,再操作的話那么處理速度會降低很多,所以每個操作完后都不斷開,下次次處理時直接發(fā)送數(shù)據(jù)包就OK了,不用建立TCP連接。

方法1:應(yīng)用層自己實現(xiàn)的心跳包 由應(yīng)用程序自己發(fā)送心跳包來檢測連接是否正常,大致的方法是:服務(wù)器在一個 Timer事件中定時 向客戶端發(fā)送一個短小精悍的數(shù)據(jù)包,然后啟動一個低級別的線程,在該線程中不斷檢測客戶端的回應(yīng), 如果在一定時間內(nèi)沒有收到客戶端的回應(yīng),即認為客戶端已經(jīng)掉線;同樣,如果客戶端在一定時間內(nèi)沒 有收到服務(wù)器的心跳包,則認為連接不可用。方法2:TCP的KeepAlive保活機制因為要考慮到一個服務(wù)器通常會連接多個客戶端,因此由用戶在應(yīng)用層自己實現(xiàn)心跳包,代碼較多 且稍顯復(fù)雜,而利用TCP/ip協(xié)議層為內(nèi)置的KeepAlive功能來實現(xiàn)心跳功能則簡單得多。 不論是服務(wù)端還是客戶端,一方開啟KeepAlive功能后,就會自動在規(guī)定時間內(nèi)向?qū)Ψ桨l(fā)送心跳包, 而另一方在收到心跳包后就會自動回復(fù),以告訴對方我仍然在線。 因為開啟KeepAlive功能需要消耗額外的寬帶和流量,所以TCP協(xié)議層默認并不開啟KeepAlive功 能,盡管這微不足道,但在按流量計費的環(huán)境下增加了費用,另一方面,KeepAlive設(shè)置不合理時可能會 因為短暫的網(wǎng)絡(luò)波動而斷開健康的TCP連接。并且,默認的KeepAlive超時需要7,200,000 MilliSeconds, 即2小時,探測次數(shù)為5次。對于很多服務(wù)端應(yīng)用程序來說,2小時的空閑時間太長。因此,我們需要手工開啟KeepAlive功能并設(shè)置合理的KeepAlive參數(shù)。以上轉(zhuǎn)自網(wǎng)絡(luò)。心跳包機制  跳包之所以叫心跳包是因為:它像心跳一樣每隔固定時間發(fā)一次,以此來告訴服務(wù)器,這個客戶端還活著。事實上這是為了保持長連接,至于這個包的內(nèi)容,是沒有什么特別規(guī)定的,不過一般都是很小的包,或者只包含包頭的一個空包。   在TCP的機制里面,本身是存在有心跳包的機制的,也就是TCP的選項:SO_KEEPALIVE。系統(tǒng)默認是設(shè)置的2小時的心跳頻率。但是它檢查不到機器斷電、網(wǎng)線拔出、防火墻這些斷線。而且邏輯層處理斷線可能也不是那么好處理。一般,如果只是用于保活還是可以的。   心跳包一般來說都是在邏輯層發(fā)送空的echo包來實現(xiàn)的。下一個定時器,在一定時間間隔下發(fā)送一個空包給客戶端,然后客戶端反饋一個同樣的空包回來,服務(wù)器如果在一定時間內(nèi)收不到客戶端發(fā)送過來的反饋包,那就只有認定說掉線了。   其實,要判定掉線,只需要send或者recv一下,如果結(jié)果為零,則為掉線。但是,在長連接下,有可能很長一段時間都沒有數(shù)據(jù)往來。理論上說,這個連接是一直保持連接的,但是實際情況中,如果中間節(jié)點出現(xiàn)什么故障是難以知道的。更要命的是,有的節(jié)點(防火墻)會自動把一定時間之內(nèi)沒有數(shù)據(jù)交互的連接給斷掉。在這個時候,就需要我們的心跳包了,用于維持長連接,保活。   在獲知了斷線之后,服務(wù)器邏輯可能需要做一些事情,比如斷線后的數(shù)據(jù)清理呀,重新連接呀……當然,這個自然是要由邏輯層根據(jù)需求去做了。   總的來說,心跳包主要也就是用于長連接的保活和斷線處理。一般的應(yīng)用下,判定時間在30-40秒比較不錯。如果實在要求高,那就在6-9秒。心跳檢測步驟:1客戶端每隔一個時間間隔發(fā)生一個探測包給服務(wù)器2客戶端發(fā)包時啟動一個超時定時器3服務(wù)器端接收到檢測包,應(yīng)該回應(yīng)一個包4如果客戶機收到服務(wù)器的應(yīng)答包,則說明服務(wù)器正常,刪除超時定時器5如果客戶端的超時定時器超時,依然沒有收到應(yīng)答包,則說明服務(wù)器掛了、一個最簡單的長連接與心跳保持的示例程序/*! ****************************************************************************** ****************************************************************************** */#include <stdio.h>#include <string.h>#include <errno.h>#include <sys/socket.h>#include <resolv.h>#include <stdlib.h>#include <netinet/in.h>#include <arpa/inet.h>#include <arpa/inet.h>#include <unistd.h>#include <sys/time.h>#include <sys/types.h>#define MAXBUF 1024int main(int argc, char **argv){  int sockfd, len;  struct sockaddr_in dest;  char buffer[MAXBUF];  char heartbeat[20] = "hello server";  fd_set rfds;  struct timeval tv;  int retval, maxfd = -1;  if (argc != 3)  {    PRintf("error! the right format should be : /          /n/t/t%s IP port/n/t eg:/t%s127.0.0.1 80/n",          argv[0], argv[0]);    exit(0);  }  if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)  {    perror("Socket");    exit(errno);  }  bzero(&dest, sizeof(dest));  dest.sin_family = AF_INET;  dest.sin_port = htons(atoi(argv[2]));  memset(&(dest.sin_zero), 0, 8);  if (inet_aton(argv[1], (struct in_addr*)&dest.sin_addr.s_addr) == 0)  {    perror(argv[1]);    exit(errno);  }  if (connect(sockfd, (struct sockaddr*)&dest, sizeof(dest)) != 0)  {    perror("Connect");    exit(errno);  }  printf("/nReady to start chatting./n/        Direct input messages and /n/        enter to send messages to the server/n");  while (1)  {    FD_ZERO(&rfds);    FD_SET(0, &rfds);    maxfd = 0;    FD_SET(sockfd, &rfds);    if (sockfd > maxfd)      maxfd = sockfd;    tv.tv_sec = 2;    tv.tv_usec = 0;    retval = select(maxfd+1, &rfds, NULL, NULL, &tv);    if (retval == -1)    {      printf("Will exit and the select is error! %s", strerror(errno));      break;    }    else if (retval == 0)    {      //printf("No message comes, no buttons, continue to wait .../n");      len = send(sockfd, heartbeat, strlen(heartbeat), 0);      if (len < 0)      {        printf("Message '%s' failed to send ! /              The error code is %d, error message '%s'/n",              heartbeat, errno, strerror(errno));        break;      }      else      {        printf("News: %s /t send, sent a total of %d bytes!/n",              heartbeat, len);      }      continue;    }    else    {      if (FD_ISSET(sockfd, &rfds))      {        bzero(buffer, MAXBUF+1);        len = recv(sockfd, buffer, MAXBUF, 0);        if (len > 0)        {          printf("Successfully received the message: '%s',%d bytes of data/n",                  buffer, len);        }        else        {          if (len < 0)              printf("Failed to receive the message! /                    The error code is %d, error message is '%s'/n",                    errno, strerror(errno));          else              printf("Chat to terminate!/n");          break;        }      }      if (FD_ISSET(0, &rfds))      {        bzero(buffer, MAXBUF+1);        fgets(buffer, MAXBUF, stdin);        if (!strncasecmp(buffer, "quit", 4))        {          printf("Own request to terminate the chat!/n");          break;        }        len = send(sockfd, buffer, strlen(buffer)-1, 0);        if (len < 0)        {          printf("Message '%s' failed to send ! /                The error code is %d, error message '%s'/n",                buffer, errno, strerror(errno));          break;        }        else        {          printf("News: %s /t send, sent a total of %d bytes!/n",                buffer, len);        }      }    }  }  close(sockfd);  return 0;}


發(fā)表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發(fā)表
主站蜘蛛池模板: 宣汉县| 凯里市| 香格里拉县| 汤阴县| 河间市| 正定县| 西平县| 丰镇市| 竹山县| 咸丰县| 黄陵县| 凤山县| 佳木斯市| 德庆县| 尼木县| 湘乡市| 鄂尔多斯市| 永城市| 新安县| 隆德县| 瑞安市| 封丘县| 米脂县| 海城市| 巴塘县| 临安市| 夏津县| 若尔盖县| 游戏| 杭锦后旗| 辰溪县| 疏勒县| 正安县| 麻城市| 桐庐县| 松潘县| 嘉荫县| 静乐县| 安溪县| 邛崃市| 德江县|