Linux下套接字詳解(四)----簡單的TCP套接字應用(迭代型)

TCP編程流程說明

(1)SERVER 服務器端編程流程

TCP服務器端編程流程如下:

① 創建套接字socket; 
② 綁定套接字bind; 
③ 設置套接字爲監聽模式,進入被動接受連接狀態listen; 
④ 接受請求,建立連接accpet; 
⑤ 讀寫數據read/write; 
⑥ 終止連接close。

(2) CLIENT客戶端編程流程

TCP客戶端編程流程如下:

① 創建套接字socket; 
② 與遠程服務器建立連接connect; 
③ 讀寫數據read/write; 
④ 終止連接close。

異常機制


3) TCP服務器三種異常情況

TCP服務器有三種異常情況,分別爲服務器主機崩潰服務器主機崩潰後重啓服務器主機關機

服務器主機崩潰

在服務器主機崩潰的情況下,已有的TCP網絡連接上發不出任何東西。 
此時客戶端發出數據後,會一直阻塞在套接字的讀取響應。但是由於服務器主機已崩潰,TCP客戶端會持續重傳數據分節,試圖從服務器接收一個ACK[一般重傳12次(源自Berkeley的實現)]後,客戶TCP最終選擇放棄,返回給應用經常一個ETIMEDOUT錯誤;或者是因爲中間路由器判定服務器主機不可達,則返回一個目的地不可達的ICMP消息響應,其錯誤代碼爲EHOSTUNREACH或ENETUNREACH。 
簡單來說,客戶端會一直阻塞與read調用,然後一直重傳,直到最後超時,客戶最終會發現服務器主機已崩潰或主機不可達,然後返回一個狀態碼,但是這個過程可能是很長就的,解決的方法就是自己寫一個read函數然後設置超時,或者加一個SO_KEEPALIVE選項,也可以通過設置套接字選項可以更改TCP持續重傳等待的超時時間。

服務器主機崩潰後重啓

在服務器主機崩潰後重啓的情況下,如果客戶在主機崩潰重啓前不主動發送數據,那麼客戶是不會知道服務器已崩潰。

在服務器重啓後,客戶向服務器發送一個數據分節;由於服務器重啓後丟失了以前的連接信息(儘管在服務端口上有進程監聽,但連接套接字所在的端口無進程等待),因此導致服務器主機的TCP響應RST;而客戶由於之前未收到服務器的響應數據,頁阻塞於read調用,當客戶端收到這個RST之後便返回錯誤ECONNRESET。

如果客戶對服務器的崩潰情況很關心,即使客戶不主動發送數據也這樣,這需要進行相關設置(如設置套接口選項SO_KEEPALIVE或某些客戶/服務器心跳函數)。

服務器主機關機 
這裏一般指的是正常關機,因爲Unix系統關機時,會發送SIGTERM和SIGKILL信號,SIGTREM可能忽略,但是SIGKILL信號不能忽略,於是服務器將由SIGKILL終止, 
當服務器主機關機的情況下,由於init進程給所有運行的進程發信號SIGTERM,這時服務器程序可以捕獲該信號,並在信號處理程序中正常關閉網絡連接。如果服務器程序忽略了SIGTERM信號,則init進程會等待一段固定的時間(通常是5s~20s),然後給所有還在運行的程序發信號SIGKILL。服務器將由信號SIGKILL終止,其終止時,所有打開的描述字被關閉,這導致向客戶發送FIN分節,客戶收到FIN分節後,能推斷出服務器將終止服務。

簡單的TCP套接字應用程序


我們下面將實現一個迭代類型的簡單TCP服務器與客戶端,實現客戶端從服務器上傳/下載文件(我們的程序中主要是上傳)。

TCP服務器

/**********************************************************
    > File Name: server.c
    > Author: GatieMe
    > Mail: [email protected]
    > Created Time: 2015年04月11日 星期六 16時22分10秒
 *********************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>

#include <netinet/in.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/wait.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <signal.h>

#define TCP_SERVER_PORT     6666    /*  服務器的端口  */
#define BUFFER_SIZE         4096
#define IP_SIZE             20
#define MAX_FILENAME_SIZE   256
#define LISTEN_QUEUE        20

/* 服務器接收從客戶端傳送來的文件  */
void
TcpServerPullFile(
            int         connfd,                     /*  服務器與客戶端通訊的套接字文件  */
            struct      sockaddr_in clientAddr,     /*  與之通信的客戶端的信息  */
            char        *fileServerRoot)            /*  上傳文件的存儲路徑  */
{
    char    buffer[BUFFER_SIZE];
    char    filename[MAX_FILENAME_SIZE];
    char    fileServerPath[MAX_FILENAME_SIZE]/* = fileServerRoot*/;
    // 定義文件流
    FILE    *stream;

    int     count;              /*  發送文件名的字節數目  */
    int     dataLength;         /*  接收到的數據大小  */
    int     writeLength;        /* 實際寫入的數據大小  */
    int     flag = 0;

    bzero(buffer, BUFFER_SIZE);
    /*
     *  向客戶端提示輸入文件路徑提示...
     *
     * strcpy(buffer, "請輸入要傳輸的文件的完整路徑:");
    strcat(buffer, "\n");

    send(new_server_socket, buffer, BUFFER_SIZE, 0);
    bzero(buffer, BUFFER_SIZE);
    */

    /*  首先獲取客戶端發送過來的文件名  */
    count = recv(connfd, buffer, BUFFER_SIZE, 0);

    if(count < 0)
    {
        perror("獲取文件名失敗...\n");
        exit(1);
    }
    else
    {

        strncpy(filename, buffer, strlen(buffer) > MAX_FILENAME_SIZE ? MAX_FILENAME_SIZE : strlen(buffer));
        strcpy(fileServerPath, fileServerRoot);
        strcat(fileServerPath, filename);
        printf("\n獲取客戶端發送過來的文件名成功...\n");
        printf("文件名[%s]\n", filename);
        printf("文件存儲路徑[%s]\n\n", fileServerPath);
    }

    //  服務器接受數據, 首先打開一個文件流
    if((stream = fopen(fileServerPath, "w")) == NULL)
    {
        perror("file open error...\n");
        exit(1);
    }
    else
    {
        bzero(buffer,BUFFER_SIZE);
    }

    printf("正在接收來自%s的文件....\n",inet_ntoa(clientAddr.sin_addr));

    dataLength = 0;


    /*  先將數據接受到緩衝區buffer中,再寫入到新建的文件中  */
    while((dataLength = recv(connfd, buffer, BUFFER_SIZE, 0)) > 0)
    {

        flag++;

        if(flag == 1)
        {
            printf("正在接收來自%s的文件....\n", inet_ntoa(clientAddr.sin_addr));
        }

        if(dataLength < 0)
        {
            printf("接收錯誤i\n");
            exit(1);
        }

        /*  向文件中寫入數據  */
        writeLength = fwrite(buffer, sizeof(char), dataLength, stream);

        if(writeLength != dataLength)
        {
             printf("file write failed\n");
             exit(1);
        }
        bzero(buffer,BUFFER_SIZE);
    }

    if(flag > 0)
    {
        printf("%s的文件傳送完畢\n", inet_ntoa(clientAddr.sin_addr));
    }
    if(flag==0)
    {
        printf("%s的文件傳輸失敗\n", inet_ntoa(clientAddr.sin_addr));
    }

    fclose(stream);
    //rename("data",inet_ntoa(clientAddr.sin_addr));

}



/*  服務器將文件發送到客戶端
 *
 *  當用戶選擇了下載文件後,服務器將執行此操作
 *
 *  */
void TcpServerPushFile(
                    int         connfd,                  /*  服務器與客戶端通訊的套接字文件  */
                    struct      sockaddr_in clientAddr,  /*  與之通信的客戶端的信息  */
                    char        *filePath)              /*  帶發送至客戶端的文件路徑  */
{
    //send file imformation

    char    buff[BUFFER_SIZE];
    char    filename[MAX_FILENAME_SIZE];
    int     count;
    FILE    *stream;


    /* 先將文件名發送給客戶端
     * 2015-4-13 21:38 Modify
     * 發送文件名時只需要發送filePath最後的文件名filename就可以了
     * */
    bzero(buff, BUFFER_SIZE);
    strcpy(filename, strrchr(filePath, '/') + 1);
    strncpy(buff, filename, strlen(filename) > MAX_FILENAME_SIZE ? MAX_FILENAME_SIZE : strlen(filename));
    count = send(connfd, buff, BUFFER_SIZE, 0);
    printf("服務器待發送的文件名[%s]..\n", filename);

    if(count < 0)
    {
        perror("Send file information");
        exit(1);
    }

    /*  服務器開始讀取並且發送文件 : */
    if((stream = fopen(filePath, "rb")) == NULL)
    {
        printf("File :%s not found!\n",filePath);
    }
    printf("服務器打開文件成功...\n");
    printf("正在向客戶端發送文件...\n");
    bzero(buff, BUFFER_SIZE);

    int fileBlockLength = 0;
    while((fileBlockLength = fread(buff, sizeof(char), BUFFER_SIZE, stream)) > 0)
    {
        printf("讀取了:%d個數據...\n",fileBlockLength);
        if(send(connfd, buff, fileBlockLength, 0) < 0)
        {
            perror("Send file error...\n");
            perror("向客戶端發送文件失敗...\n");
            exit(1);
        }

        bzero(buff,BUFFER_SIZE);
    }

    fclose(stream);
    printf("服務器發送文件成功\n");

}



extern int errno;
int main(int argc, char *argv[])
{
    /**********************************************************
     *
     *  創建並初始化服務器套接字
     *
     **********************************************************/
    struct sockaddr_in      serverAddr;
    int                     socketFd;

    bzero(&serverAddr, sizeof(serverAddr));     /*  全部置零  */

    /* 設置地址相關的屬性 */
    serverAddr.sin_family         =   AF_INET;
    serverAddr.sin_addr.s_addr    =   htons(INADDR_ANY);
    serverAddr.sin_port           =   htons(TCP_SERVER_PORT);

    /*  創建套接字  */
    socketFd = socket(AF_INET, SOCK_STREAM, 0);
    if(socketFd < 0)
    {
        perror("socket create error\n");
        exit(-1);
    }
    else
    {
        printf("socket create success...\n");
        printf("創建套接字成功[errno = %d]...\n", errno);
    }

    /*  綁定端口  */
    if(bind(socketFd, (struct sockaddr*)&serverAddr, sizeof(serverAddr)) > 0)
    {
        perror("bind error\n");
        exit(1);
    }
    else
    {
        printf("server bind port %d success...\n", TCP_SERVER_PORT);
        printf("服務器綁定端口%d成功...\n", TCP_SERVER_PORT);
    }

    /*  開始監聽綁定的端口  */
    if(listen(socketFd, LISTEN_QUEUE))
    {
        printf("Server listen error[errno = %d]...\n", errno);
        exit(-1);
    }
    else
    {
        printf("Server listen success...\n");
        printf("服務器開始監聽...\n");
    }
    struct sockaddr_in  clientAddr;
    socklen_t           length = sizeof(clientAddr);
    int                 connFd;

    while( 1 )
    {
        /* accept返回一個新的套接字與客戶端進行通信  */
        connFd = accept(socketFd, (struct sockaddr*)&clientAddr, &length);

        if(connFd == -1)
        {
            printf("accept error[%d]...\n", errno);
            continue;
        }
        else
        {
            printf("獲取到從客戶端%s的連接...\n", inet_ntoa(clientAddr.sin_addr));
            ////////////////////////////////////////////////////////////////////////
            //
            //  這裏填寫服務器的處理代碼
            //
            ////////////////////////////////////////////////////////////////////////
            TcpServerPullFile(connFd, clientAddr, "./sdata/"); /*  將客戶端發送來的文件存儲在./sdata目錄下  */

            close(connFd);
        }
    }
                //        sleep(10);

}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182
  • 183
  • 184
  • 185
  • 186
  • 187
  • 188
  • 189
  • 190
  • 191
  • 192
  • 193
  • 194
  • 195
  • 196
  • 197
  • 198
  • 199
  • 200
  • 201
  • 202
  • 203
  • 204
  • 205
  • 206
  • 207
  • 208
  • 209
  • 210
  • 211
  • 212
  • 213
  • 214
  • 215
  • 216
  • 217
  • 218
  • 219
  • 220
  • 221
  • 222
  • 223
  • 224
  • 225
  • 226
  • 227
  • 228
  • 229
  • 230
  • 231
  • 232
  • 233
  • 234
  • 235
  • 236
  • 237
  • 238
  • 239
  • 240
  • 241
  • 242
  • 243
  • 244
  • 245
  • 246
  • 247
  • 248
  • 249
  • 250
  • 251
  • 252
  • 253
  • 254
  • 255
  • 256
  • 257
  • 258
  • 259
  • 260
  • 261
  • 262
  • 263
  • 264
  • 265
  • 266
  • 267
  • 268
  • 269
  • 270
  • 271
  • 272
  • 273
  • 274
  • 275
  • 276
  • 277
  • 278
  • 279
  • 280
  • 281
  • 282
  • 283
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182
  • 183
  • 184
  • 185
  • 186
  • 187
  • 188
  • 189
  • 190
  • 191
  • 192
  • 193
  • 194
  • 195
  • 196
  • 197
  • 198
  • 199
  • 200
  • 201
  • 202
  • 203
  • 204
  • 205
  • 206
  • 207
  • 208
  • 209
  • 210
  • 211
  • 212
  • 213
  • 214
  • 215
  • 216
  • 217
  • 218
  • 219
  • 220
  • 221
  • 222
  • 223
  • 224
  • 225
  • 226
  • 227
  • 228
  • 229
  • 230
  • 231
  • 232
  • 233
  • 234
  • 235
  • 236
  • 237
  • 238
  • 239
  • 240
  • 241
  • 242
  • 243
  • 244
  • 245
  • 246
  • 247
  • 248
  • 249
  • 250
  • 251
  • 252
  • 253
  • 254
  • 255
  • 256
  • 257
  • 258
  • 259
  • 260
  • 261
  • 262
  • 263
  • 264
  • 265
  • 266
  • 267
  • 268
  • 269
  • 270
  • 271
  • 272
  • 273
  • 274
  • 275
  • 276
  • 277
  • 278
  • 279
  • 280
  • 281
  • 282
  • 283

TCP客戶端


/**********************************************************
    > File Name: client.c
    > Author: GatieMe
    > Mail: [email protected]
    > Created Time: 2015年04月11日 星期六 12時05分02秒
 *********************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <netinet/in.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/wait.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <signal.h>

#define TCP_SERVER_PORT     6666
#define MAX_FILENAME_SIZE   256
#define IP_SIZE             20

#define BUFFER_SIZE         4096

/* 客戶端將文件上傳到服務器上 */
void TcpClientPushFile(int socketFd, char *filePath)
{
    FILE    *stream;
    char    buffer[BUFFER_SIZE];
    char    filename[MAX_FILENAME_SIZE];
    int     count = 0;

    bzero(buffer, BUFFER_SIZE);
    strcpy(filename, strrchr(filePath, '/') + 1);
    strncpy(buffer, filename, strlen(filename) > MAX_FILENAME_SIZE ? MAX_FILENAME_SIZE : strlen(filename));
    count = send(socketFd, buffer, BUFFER_SIZE, 0);
    printf("客戶端待上傳待文件名[%s]..\n", filename);


    if(count < 0)
    {
        perror("Send file information");
        exit(1);
    }

    /*  打開文件流  */
    if((stream = fopen(filePath, "r")) == NULL)
    {
        printf("Can't open the file [%s]\n", filePath);
        exit(1);
    }
    else
    {
        printf("客戶端打開文件成功\n");
    }

    printf("正在向服務器傳上傳文件...\n");
    count = 0;

    /*  清空緩衝區  */
    bzero(buffer, BUFFER_SIZE);

    /*  不斷讀取併發送數據  */
    while((count = fread(buffer, 1, BUFFER_SIZE, stream)) > 0)
    {
        // printf("count =%d\n", count);
        if(send(socketFd, buffer, count, 0) < 0)
        {
            printf("send file error...\n");
            break;
        }

        bzero(buffer, BUFFER_SIZE);  /*  再次將緩衝區清空  */
    }

    printf("向服務器發送文件成功...\n");

    /* 傳送完畢後, 關閉文件流  */
    if(fclose(stream))
    {
        printf("file close error\n");
        exit(1);
    }
    else
    {
        printf("關閉文件流成功...\n");
    }


    /*  關閉與服務器通訊的套接字  */
    close(socketFd);
}




/* 從服務器上下載文件  */
void TcpClientPullFile(int socketFd, char *filePath)
{
    char    buff[BUFFER_SIZE];
    char    filename[MAX_FILENAME_SIZE];
    int     count, writeLength, dataLength;
    FILE    *stream;
    bzero(buff,BUFFER_SIZE);


    /*  首先獲取服務器發送過來的文件名  */
    count = recv(socketFd, buff, BUFFER_SIZE, 0);

    if(count < 0)
    {
        perror("獲取文件名失敗...\n");
        exit(1);
    }

    strncpy(filename, buff, strlen(buff) > MAX_FILENAME_SIZE ? MAX_FILENAME_SIZE : strlen(buff));

    /*  開始接收文件  */
    printf("Preparing download file : %s", filename);

    /*  打開文件流  */
    if((stream = fopen(filename, "wb+")) == NULL)
    {
        perror("create file %s error...\n");
        perror("創建文件失敗...\n");
        exit(1);
    }

    bzero(buff, BUFFER_SIZE);          /*  清空緩衝區  */
    dataLength = 0;
    while((dataLength = recv(socketFd, buff, BUFFER_SIZE, 0)) != 0)
    {
        if(dataLength < 0)  /* 如果接收文件失敗  */
        {
            perror("download error...\n");
            perror("下載文件失敗...\n");
            exit(1);
        }


        /*  將接收到的文件數據寫入文件中  */
        writeLength = fwrite(buff, sizeof(char), dataLength, stream);
        if(writeLength < dataLength)   /*  如果寫入的數據比實際接收到的數據少  */
        {
            perror("file write error...\n");
            perror("寫入文件失敗...\n");
            exit(1);
        }

        bzero(buff, BUFFER_SIZE);               /* 清空緩衝區  */
    }
    printf("下載來自服務器%s的文件成功\n", filename);
    printf("Receieved file:%s finished!\n", filename);

    fclose(stream);             /*  關閉文件流 */

}





int main(int argc, char *argv[])
{
    char                serverIp[IP_SIZE];             /*  服務器的IP地址       */


    if(argc >= 2)                       /*  參數過多的時候,提示用戶  */
    {
        printf("You have given to much parameters...\n");
        printf("Yous should give the IP address after %s\n without any other parametes...\n", (char *)argv[0]);
    }
    else if(argc == 1)                  /*  只有一個參數,則默認使用localhost(127.0.0.1)  */
    {
        strcpy(serverIp, "127.0.0.1");
    }
    else
    {
        strcpy(serverIp, argv[1]);
    }

    /**********************************************************
     *
     *  創建並初始化套接字
     *
     **********************************************************/
    struct sockaddr_in  serverAddr;          /*  服務器的套接字信息   */
    int                 socketFd;                      /*  客戶端的套接字信息   */

    bzero(&serverAddr, sizeof(serverAddr));             /*  全部置零               */

    serverAddr.sin_family       =   AF_INET;                      /*  internet協議族         */
    serverAddr.sin_addr.s_addr  =   inet_addr(serverIp);        /*  設置所連接服務器的IP   */
    serverAddr.sin_port         =   htons(TCP_SERVER_PORT);       /*  設置連接的服務器端口   */

    /*  開始創建套接字                        */
    /*  SOCK_STREAM 面向連接的套接字,即TCP   */
    socketFd                    =   socket(AF_INET, SOCK_STREAM, 0);

    if(socketFd < 0)
    {
        printf("socket error\n");
        exit(-1);
    }

    /*  嘗試連接服務器  */
    if(connect(socketFd, (struct sockaddr*)&serverAddr, sizeof(serverAddr)) < 0)
    {
        printf("Can Not Connect To %s\n", serverIp);
        exit(1);
    }
    else
    {
        printf("connect to the server %s SUCCESS...\n", serverIp);
        printf("連接服務器成功...\n");
    }

    /**********************************************************
     *
     *  下面進行正常的套接字通信
     *
     **********************************************************/
    // 上傳文件到服務器
    TcpClientPushFile(socketFd, "./cdata/push");
    close(socketFd);

}



  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182
  • 183
  • 184
  • 185
  • 186
  • 187
  • 188
  • 189
  • 190
  • 191
  • 192
  • 193
  • 194
  • 195
  • 196
  • 197
  • 198
  • 199
  • 200
  • 201
  • 202
  • 203
  • 204
  • 205
  • 206
  • 207
  • 208
  • 209
  • 210
  • 211
  • 212
  • 213
  • 214
  • 215
  • 216
  • 217
  • 218
  • 219
  • 220
  • 221
  • 222
  • 223
  • 224
  • 225
  • 226
  • 227
  • 228
  • 229
  • 230
  • 231
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182
  • 183
  • 184
  • 185
  • 186
  • 187
  • 188
  • 189
  • 190
  • 191
  • 192
  • 193
  • 194
  • 195
  • 196
  • 197
  • 198
  • 199
  • 200
  • 201
  • 202
  • 203
  • 204
  • 205
  • 206
  • 207
  • 208
  • 209
  • 210
  • 211
  • 212
  • 213
  • 214
  • 215
  • 216
  • 217
  • 218
  • 219
  • 220
  • 221
  • 222
  • 223
  • 224
  • 225
  • 226
  • 227
  • 228
  • 229
  • 230
  • 231

由於TCP和UDP在實現流程上有很多異曲同工之處,因此我們後面的拓展優化將主要針對TCP套接字程序,我們在下一篇開始UDP的套接字編程詳解,理解了TCP不同的實現思想之後稍加修改即可。。。。

運行情況

TcpServer服務器 
TcpServer客戶端

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章