1. 程式人生 > >利用網路套接字實現TCP互動

利用網路套接字實現TCP互動

我們來了解一下TCP互動流程:
這裡寫圖片描述

大致流程如下:
(1)伺服器根據地址的型別(屬於ipv4還是ipv6等)、socket型別(比如TCP、UDP)去建立socket,創建出的套接字socket本質上是個檔案描述符
(2)伺服器繫結IP地址和埠號到套接字socket
(3)伺服器socket**監聽**埠號請求,隨時準備接收客戶端發來的連線,但這個時候伺服器的socket並沒有被開啟。
(4)根據地址的型別(屬於ipv4還是ipv6等)、socket型別(比如TCP、UDP)去**建立socke**t,創建出的套接字socket本質上也是個檔案描述符。
(5)客戶端根據伺服器的ip地址和埠號

,試圖連線伺服器
(6)伺服器socket**接收到客戶端的socket請求,被動開啟,開始接收客戶端的請求並等待客戶端返回連線資訊。這個階段,伺服器的**accept方法是阻塞的,即等到剛才試圖連線的客戶端返回連線資訊,accept方法才能返回,才能繼續接收下一個最新的客戶端連線請求。
(7)客戶端連線成功,向伺服器傳送連線狀態資訊
(8)伺服器accept方法返回,連線成功
(9)客戶端傳送訊息
(10)服務端接收訊息
(11)客戶端關閉
(12)服務端關閉

我們根據這個流程實現TCP互動:
tcpserver.c(伺服器)

#include <stdio.h>                        
#include <unistd.h> #include <sys/socket.h> #include <sys/types.h> #include <string.h> #include <errno.h> #include <netinet/in.h> #include <arpa/inet.h> //伺服器 int main(int argc, char* argv[]) { if(argc!=3){ printf("Usage %s is port\n",argv[0]); return
1; } //建立套接字 int sock = socket(AF_INET, SOCK_STREAM, 0); if(sock < 0){ perror("socket"); return 2; } struct sockaddr_in local; local.sin_family = AF_INET; local.sin_port = htons(atoi(argv[2])); local.sin_addr.s_addr = inet_addr(argv[1]); //繫結 if(bind(sock, (struct sockaddr*)&local, sizeof(local))<0) { perror("bind"); return 3; } //監聽 if(listen(sock, 5)<0) { perror("listen"); return 4; } while(1) { char buf[1024]; buf[0]='\0'; struct sockaddr_in peer; socklen_t len = sizeof(peer); //接受請求 int new_sock=accept(sock, (struct sockaddr*)&peer,&len); if(new_sock<0) { perror("accept"); return 5; } inet_ntop(AF_INET, &peer.sin_addr, buf, sizeof(buf)); printf("get a connect,ip:%s,port:%d\n",buf, ntohs(peer.sin_port)); while(1) { ssize_t s = read(new_sock, buf, sizeof(buf)); if(s > 0) { buf[s]='\0'; printf("[%s:%d] %s",inet_ntoa(peer.sin_addr),\ ntohs(peer.sin_port),buf); } else { printf("client quit\n"); break; } write(new_sock,buf,strlen(buf)+1); } } close(sock); return 0; }

tcpclient.c(客戶端)

#include <stdio.h>                           
#include <stdlib.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <string.h>
#include <errno.h>
#include <netinet/in.h>
#include <arpa/inet.h>

int main(int argc,char *argv[])
{
    if(argc != 3){
        printf("Usage %s ip port\n",argv[0]);
        return 1;
    }

    //建立套接字
    int sock=socket(AF_INET,SOCK_STREAM, 0);
    if(sock < 0)
    {
        perror("socket");
        return 2;
    }

    struct sockaddr_in server;
    server.sin_family = AF_INET;
    server.sin_port = htons(atoi(argv[2]));
    server.sin_addr.s_addr = inet_addr(argv[1]);

    //建立連線
    int ret = connect(sock, (struct sockaddr*)&server, \
            sizeof(server));
    if(ret < 0){
        perror("connect");
        return 3;
    }

    printf("connect success...\n");

    while(1){
        char buf[1024];//緩衝區
        buf[0]='\0';
        printf("Please Enter:");
        fflush(stdout);
        ssize_t s = read(0, buf, sizeof(buf));                              
        }
        write(sock, buf, sizeof(buf));
        if(strncmp(buf, "quit",4)==0)
            break;
        read(sock, buf, sizeof(buf));
        printf("server :%s",buf);
    }

    close(sock);
    return 0;
}         

在本地網路中建立連線,執行結果如下:
這裡寫圖片描述