使用TCP收發(fā)消息需要處理的常見問題

要實(shí)現(xiàn)服務(wù)器和客戶端之間完整的收發(fā)消息,需要處理以下的幾個(gè)問題。

粘包半包問題

粘包就是一次從socket緩沖區(qū)中讀取到的數(shù)據(jù)不止一條消息。半包就是一次從socket緩沖區(qū)讀取的數(shù)據(jù)只是一條消息的部分。

要解決粘包半包的問題,常用的方法有長度信息法、固定長度法和結(jié)束符號(hào)法。一般的游戲開發(fā)中使用的長度信息法。

長度信息法在要發(fā)送的信息前面,加上一個(gè)固定長度的信息長度信息,解析的時(shí)候,先讀出這個(gè)固定長度的信息數(shù)據(jù),然后讀取信息長度的數(shù)據(jù)??梢姡@個(gè)方法的核心是實(shí)現(xiàn)一個(gè)能從socket緩沖區(qū)讀取指定長度數(shù)據(jù)的函數(shù)。

從socket緩沖區(qū)中讀取指定長度的數(shù)據(jù),可以參考《unix網(wǎng)絡(luò)編程》中的readn函數(shù)。

ssize_t                     /* Read "n" bytes from a descriptor. */
readn(int fd, void *vptr, size_t n)
{
    size_t  nleft;
    ssize_t nread;
    char    *ptr;

    ptr = vptr;
    nleft = n;
    while (nleft > 0) {
        if ( (nread = read(fd, ptr, nleft)) < 0) {
            if (errno == EINTR)
                nread = 0;      /* and call read() again */
            else
                return(-1);
        } else if (nread == 0)
            break;              /* EOF */

        nleft -= nread;
        ptr   += nread;
    }
    return(n - nleft);      /* return >= 0 */
}
/* end readn */

不完整發(fā)送問題

當(dāng)socket的緩沖區(qū)滿了的時(shí)候,再往緩沖區(qū)寫數(shù)據(jù),寫入的數(shù)據(jù)可能小于要發(fā)送的數(shù)據(jù)。如果不對這種情況進(jìn)行處理,那發(fā)送的數(shù)據(jù)就可能不完整。因此,我們需要一個(gè)向緩沖區(qū)寫入固定長度數(shù)據(jù)的函數(shù),同樣,我們也可以參考《UNIX網(wǎng)絡(luò)編程》中的寫法。

ssize_t                     /* Write "n" bytes to a descriptor. */
writen(int fd, const void *vptr, size_t n)
{
    size_t      nleft;
    ssize_t     nwritten;
    const char  *ptr;

    ptr = vptr;
    nleft = n;
    while (nleft > 0) {
        if ( (nwritten = write(fd, ptr, nleft)) <= 0) {
            if (nwritten < 0 && errno == EINTR)
                nwritten = 0;       /* and call write() again */
            else
                return(-1);         /* error */
        }

        nleft -= nwritten;
        ptr   += nwritten;
    }
    return(n);
}
/* end writen */

大端小端問題

因?yàn)橄⑶懊嬗幸粋€(gè)表示長度的數(shù)字,而數(shù)字的表示有大端小端之分,要處理這個(gè)問題,只需要規(guī)定傳輸?shù)臄?shù)字是大端表示還是小端表示。然后,在傳輸?shù)臅r(shí)候進(jìn)行判斷,如果和傳輸?shù)谋硎痉绞讲煌M(jìn)行轉(zhuǎn)換即可。在收到數(shù)字的時(shí)候,使用自定義的函數(shù)來解析這個(gè)數(shù)字。

連接斷開的問題

游戲開發(fā)中,客戶端通常要和服務(wù)器保持TCP連接,這時(shí)候,就需要處理連接斷開問題了。當(dāng)發(fā)送消息的時(shí)候,需要檢查連接是否正常。關(guān)閉的時(shí)候,要檢查緩沖區(qū)的數(shù)據(jù)是否已經(jīng)發(fā)送完畢,要等數(shù)據(jù)發(fā)送完畢才能關(guān)閉。

我對這方面不是很熟,先寫這么多吧。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容