1. 程式人生 > >Linux學習之網路程式設計(TCP程式設計)

Linux學習之網路程式設計(TCP程式設計)

言之者無罪,聞之者足以戒。 - “詩序”

1,TCP是什麼?

TCP傳輸控制協議

向用戶程序提供可靠的全雙工位元組流(位元組流:給每一個位元組編序)

2,UDP是什麼?

UDP使用者資料報協議

是一種無連線的協議

3,獲取時間服務的客戶端

(1),建立一個的的IPv4(AF_INET)的位元組流(SOCK_STREAM)套接字

(2),連線到IP地址,埠號為8888的伺服器

(3),寫一個數據到伺服器

(4),接收伺服器傳回來的資料並顯示到標準輸出

(5),關閉套接字

下面來看一下客戶端的程式:

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

int main(int argc,char *argv[])
{
        int sockfd;
        struct sockaddr_in servaddr;
        char buf[100];//儲存讀取的內容
        int bytes;//儲存讀取的位元組數

        if((sockfd = socket(AF_INET,SOCK_STREAM,0)) < 0)//建立套接字
        {
                printf("socket error\n");
                return -1;
        }
        //結構體中成員變數初始化為0     
        bzero(&servaddr,sizeof(servaddr));
        //初始化成員變數
        servaddr.sin_family = AF_INET;//IPv4
        servaddr.sin_addr.s_addr = inet_addr("192.168.177.133");//轉換為地址格式
        servaddr.sin_port = htons(8888);//主機序轉換到網路序
        //連線伺服器
        if(connect(sockfd,(struct sockaddr *)&servaddr,sizeof(servaddr)) < 0)//繫結伺服器ip和埠到>套結字
        {
                perror("connect error");
                return -2;
        }
        //儲存讀取的資料和讀取的位元組數
        bytes == read(sockfd,buf,100);
        if(bytes < 0)
        {
                printf("Error ,read failed\n");
                return -3;
        }
        //如果讀取的位元組數為0 ,就說明連線已經關閉了
        if(0 == bytes)
        {
                printf("Server close connection\n");
                return -4;

        }
        //列印讀取的位元組數和讀取的內容
        printf("read bytes %d\n",bytes);
        printf("Time: %s\n",buf);
        //關閉套結字
        close(sockfd);
        return 0;
}
  

上面的程式的設計思路已經說了,我也在程式中寫了必要的註釋,相信是比較容易接受。

如圖4所示,提供時間的伺服器端:

(1),繫結已知的IPv4的的的的地址(INADDR_ANY)和埠號(8888)

(2),將套接字轉換成監聽套接字

(3),睡眠等待客戶端連線

(4),讀取客戶端資料

(5),將收到的資料傳送給客戶端

(6),睡眠1S後關閉套接字

接下來看一下伺服器的程式:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <unistd.h>
#include <fcntl.h>
#define MAX_LISTEN_QUE 5

int main(int argc,char *argv[])
{
        int listenfd,sockfd,opt=1;//listenfd建立的普通套接字,sockfd通訊套接字
        struct sockaddr_in server,client;
        char buf[200];
        socklen_t len;
        int timep;
        int ret;
        //建立套接字
        listenfd = socket(AF_INET,SOCK_STREAM,0);
        if(listenfd < 0)
        {
                perror("Create socket fail");
                return -1;
        //設定套結字關聯的選項(設定地址的重用)
        if((ret = setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt))) < 0)
        {
                perror("Error ,set socket reuse addr failed");
                return -1;
        }
        //清空結構體中的變數值
        bzero(&server, sizeof(server));
        //初始化結構體的變數
        server.sin_family = AF_INET;//IPv4
        server.sin_port   = htons(8888);//主機轉換到網路
        server.sin_addr.s_addr  = htonl(INADDR_ANY);//同上(使用這個巨集套接字可以繫結到所有的端>口)
        //獲取結構體地址長度
        len = sizeof(struct sockaddr);
        //繫結伺服器ip地址和埠到套接字
        if(bind(listenfd, (struct sockaddr *)&server, len)<0)
        {
                perror("bind error.");
                return -1;
        }
        //設定伺服器的最大連線數
        listen(listenfd, MAX_LISTEN_QUE);
        //迭代(就是可以有多個客戶端只是不能同時通訊)
        while(1)
        {
           //等待客戶端請求,如果請求到來,返回一個新的socket
           //伺服器和客戶端利用新的socket來通訊
            sockfd = accept(listenfd, (struct sockaddr *)&client, &len);
            if(sockfd < 0)
            {
                perror("accept error.");
                return -1;
            }
            //顯示系統的當前時間 
            timep = time(NULL);
            //將資料按照一定的格式轉換之後複製到buf
            //ctime返回一個表示當地時間的字串
            snprintf(buf, sizeof(buf), "%s", ctime(&timep));
            //向套接字中寫入buf儲存的時間
            write(sockfd, buf, strlen(buf));
            //列印儲存的位元組數
            printf("Bytes:%d\n", strlen(buf));
            //列印套接字的檔案描述符
            printf("sockfd=%d\n", sockfd);
           //關閉套接字
            close(sockfd);
        }
        return 0;
}