久久国产成人av_抖音国产毛片_a片网站免费观看_A片无码播放手机在线观看,色五月在线观看,亚洲精品m在线观看,女人自慰的免费网址,悠悠在线观看精品视频,一级日本片免费的,亚洲精品久,国产精品成人久久久久久久

分享

Linux Socket學(xué)習(xí)(二)

 Love_Bear 2010-03-08

創(chuàng)建套接口
在這一部分,,我們將會(huì)看到創(chuàng)建套接口與創(chuàng)建管道一樣的容易,。雖然有一些我們將會(huì)了解到的函數(shù)參數(shù),。為了能創(chuàng)建成功,,這些參數(shù)必須提供合適的值。
socketpair函數(shù)概要如下:
#include <sys/types.h>
#include <sys/socket.h>
int socketpair(int domain, int type, int protocol, int sv[2]);
sys/types.h文件需要用來(lái)定義一些C宏常量,。sys/socket.h文件必須包含進(jìn)來(lái)定義socketpair函數(shù)原型,。
socketpair函數(shù)需要四個(gè)參數(shù)。他們是:
套接口的域
套接口類型
使用的協(xié)議
指向存儲(chǔ)文件描述符的指針
domain參數(shù)直到第2單我們才會(huì)解釋,。對(duì)于socketpair函數(shù)而言,,只需提供C宏AF_LOCAL。
類型參數(shù)聲明了我們希望創(chuàng)建哪種類型的套接口,。socketpair函數(shù)的選擇如下:
SOCK_STREAM
SOCK_DGRAM
套接口類型的選擇我們將會(huì)在第4章談到,。在這一章中,我們只需要簡(jiǎn)單的使用SOCK_STREAM套接口類型,。
對(duì)于socketpair函數(shù),,protocol參數(shù)必須提供為0。
參數(shù)sv[2]是接收代表兩個(gè)套接口的整數(shù)數(shù)組,。每一個(gè)文件描述符代表一個(gè)套接口,,并且與另一個(gè)并沒(méi)有區(qū)別。
如果函數(shù)成功,,將會(huì)返回0值,。否則將會(huì)返回-1表明創(chuàng)建失敗,并且errno來(lái)表明特定的錯(cuò)誤號(hào),。
使用socketpair的例子
為了演示如何使用socketpair函數(shù),,我們用下面的例子來(lái)進(jìn)行演示。
1:  /* Listing 1.1:
2:   *
3:   * Example of socketpair(2) function:
4:   */
5:  #include <stdio.h>
6:  #include <stdlib.h>
7:  #include <unistd.h>
8:  #include <errno.h>
9:  #include <string.h>
10: #include <sys/types.h>
11: #include <sys/socket.h>
12:
13: int
14: main(int argc,char **argv) {
15:     int z;                    /* Status return code */
16:     int s[2];                 /* Pair of sockets */
17:
18:     /*
19:      * Create a pair of local sockets:
20:      */
21:     z = socketpair(AF_LOCAL,SOCK_STREAM,0,s);
22:
23:     if ( z == -1 ) {
24:         fprintf(stderr,
25:             "%s: socketpair(AF_LOCAL,SOCK_STREAM,0)\n",
26:             strerror(errno));
27:        return 1;            /* Failed */
28:   }
29:
30:   /*
31:     * Report the socket file descriptors returned:
32:     */
33:   printf("s[0] = %d;\n",s[0]);
34:   printf("s[1] = %d;\n",s[1]);
35:
36:   system("netstat --unix -p");
37:
38:   return 0;
39: }
演示程序的描述如下:
1 在第16行聲明數(shù)組s[2]用來(lái)存儲(chǔ)用來(lái)引用兩個(gè)新創(chuàng)建的套接口的文件描述符,。
2 在第21行調(diào)用socketpair函數(shù),。domain參數(shù)指定為AF_LOCAL,套接口類型參數(shù)指定為SOCK_STREAM,,而協(xié)議指定為0,。
3 23行的if語(yǔ)句用來(lái)測(cè)試socketpair函數(shù)是否成功。如果z的值為-1,就會(huì)向標(biāo)準(zhǔn)錯(cuò)誤發(fā)送報(bào)告,,并且在27行退出程序,。
4 如果函數(shù)調(diào)用成功,,控制語(yǔ)句就會(huì)轉(zhuǎn)到33,并且在34行向標(biāo)準(zhǔn)輸出報(bào)告返回的文件單元數(shù)。
5 36行使用system函數(shù)來(lái)調(diào)用netstat命令,。命令選項(xiàng)--unix表明只報(bào)告Unix套接口,,-p選項(xiàng)則是要報(bào)告進(jìn)程信息。
使用提供的Makefile,,我們可以用make命令來(lái)編譯這個(gè)程序:
$ make 01lst01
gcc -c -D_GNU_SOURCE -Wall 01LST01.c
gcc 01LST01.o -o 01lst01
為了執(zhí)行這個(gè)演示程序,,我們可以執(zhí)行下面的命令:
$ ./01lst01
程序的執(zhí)行結(jié)果如下:
1:  $ ./01lst01
2:  s[0] = 3;
3:  s[1] = 4;
4:  (Not all processes could be identified, non-owned process info
5:    will not be shown, you would have to be root to see it all.)
6:  Active UNIX domain sockets (w/o servers)
7:  Proto RefCnt Flags      Type      . . . I-Node PID/Program name  Path
8:  unix 1        []        STREAM   . . . 406    -                 @00000019
9:  unix 1        []        STREAM   . . . 490    -                 @0000001f
10: unix 1        []        STREAM   . . . 518    -                 @00000020
11: unix 0        []        STREAM   . . . 117    -                 @00000011
12: unix 1        []        STREAM   . . . 789    -                 @00000030
13: unix 1        []        STREAM   . . . 549    -                 @00000023
14: unix 1        []        STREAM   . . .1032    662/01lst01
15: unix 1        []        STREAM   . . .1031    662/01lst01
16: unix 1        []        STREAM   . . . 793    -                 /dev/log
17: unix 1        []        STREAM   . . . 582    -                 /dev/log
18: unix 1        []        STREAM   . . . 574    -                 /dev/log
19: unix 1        []        STREAM   . . . 572    -                 /dev/log
20: unix 1        []        STREAM   . . . 408    -                 /dev/log
21: $
在我們上面的輸入顯示中,在第1行調(diào)用可執(zhí)行程序01LST01,。第2行和第3行顯示了我們?cè)谖募枋龇?和4上打開(kāi)套接口,。接下來(lái)的4到20行是程序中netstat命令的輸出。
盡管這個(gè)程序并沒(méi)有使用創(chuàng)建的套接口來(lái)做任何事情,,但是他確實(shí)演示了套接口的創(chuàng)建,。并且他演示了套接口單元數(shù)的分配與打開(kāi)的文件的方式一樣。
在套接口上執(zhí)行I/O操作
我們?cè)谇懊嬉呀?jīng)了解到套接口可以像任何打開(kāi)的文件一樣向其中寫(xiě)入或是從中讀取,。在這一部分將我們將會(huì)親自演示這一功能,。然而為了試都討論的完整,我們先來(lái)看一下read,,write,close的函數(shù)概要:
#include <unistd.h>
ssize_t read(int fd, void *buf, size_t count);
ssize_t write(int fd, const void *buf, size_t count);
int close(int fd);
這些應(yīng)是我們已經(jīng)熟悉的Linux的輸入/輸入函數(shù),。通過(guò)回顧我們可以看到,read函數(shù)返從文件描述符fd中返回最大count字節(jié)的輸入,,存放到buf緩沖區(qū)中,。返回值代表實(shí)際讀取的字節(jié)數(shù),。如果返回0則代表文件結(jié)束,。
write函數(shù)將我們指定的buf緩沖區(qū)中總計(jì)count的字節(jié)寫(xiě)入文件描述符fd中。返回值代表實(shí)際寫(xiě)入的字節(jié)數(shù),。通常這必須與指定的count參數(shù)相匹配,。然而也會(huì)有一些情況,這個(gè)值要count小,,但是我們沒(méi)有必要擔(dān)心這樣的情況,。
最后,如果文件成功關(guān)閉close就會(huì)返回0,。對(duì)于這些函數(shù),,如果返回-1則表明有錯(cuò)誤發(fā)生,并且錯(cuò)誤原因?qū)?huì)發(fā)送到外部變量errno中,。為了可以訪問(wèn)這個(gè)變量,,我們需要在源文件中包含errno.h頭文件。
下面的例子是在套接口的兩個(gè)方向上執(zhí)行讀取與寫(xiě)入操作,。
/*****************************************
 *
 * Listing 1.2
 *
 * Example performing I/O on s socket pair:
 *
 * ******************************************/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>

int main(int argc,char **argv)
{
    int z;        /* Status return code */
    int s[2];    /* Pair of sockets */
    char *cp;    /* A work pointer */
    char buf[80];    /* work buffer */

    /*
     * Create a pair of local sockets:
     */

    z = socketpair(AF_LOCAL,SOCK_STREAM,0,s);

    if(z == -1)
    {
        fprintf(stderr,
                "%s:socketpair(AF_LOCAL,SOCK_STREAM,""0)\n",strerror(errno));
        return 1;    /* Failed */
    }

    /*
     * Write a message to socket s[1]:
     */

    z = write(s[1],cp="Hello?",6);
    if(z<0)
    {
        fprintf(stderr,"%s:wirte(%d,\"%s\",%d)\n",strerror(errno),s[1],cp,strlen(cp));
        return 2;    /* Failed */
    }

    printf("Wrote message '%s' on s[1]\n",cp);

    /*
     * Read from socket s[0]:
     */

    z = read(s[0],buf,sizeof buf);
    if(z < 0)
    {
        fprintf(stderr,"%s:read(%d,buf,%d)\n",
                strerror(errno),s[0],sizeof buf);
        return 3;    /* Failed */
    }

    /*
     * Report received message:
     */

    buf[z] = 0;    /* NUL terminate */
    printf("Recevie message '%s' from socket s[0]\n",buf);

    /*
     * Send a reply back to s[1] from s[0]:
     */

    z = write(s[0],cp="Go away!",8);
    if(z < 0)
    {
        fprintf(stderr,"%s:write(%d,\"%s\",%d)\n",
                strerror(errno),s[0],cp,strlen(cp));
        return 4;    /* Failed */
    }

    printf("Wrote message '%s' on s[0]\n",cp);

    /*
     * Read from socket s[1]:
     */

    z = read(s[1],buf,sizeof buf);
    if(z < 0)
    {
        fprintf(stderr,"%s:read(%d,buf,%d)\n",
                strerror(errno),s[1],sizeof buf);
        return 3;    /* Failed */
    }

    /*
     * Report message recevied by s[0]:
     */
    buf[z] = 0;    /*NUL terminate */
    printf("Received message '%s' from socket s[1]\n",
            buf);

    /*
     * Close the sockets:
     */
    close(s[0]);
    close(s[1]);

    puts("Done");
    return 0;
}
程序調(diào)用的步驟總結(jié)如下:
1 在第23行調(diào)用socketpair函數(shù),,如果成功返回,,則將生成的套接口存放在數(shù)組s中。
2 在第25行測(cè)試函數(shù)是否成功,,如果發(fā)生錯(cuò)誤,,將會(huì)報(bào)告錯(cuò)誤。
3 在第36行一個(gè)由6個(gè)字符組成的消息"Hello?"寫(xiě)入套接口s[1],。注意并沒(méi)有寫(xiě)入空字節(jié),,因?yàn)樵趙rite函數(shù)的count參數(shù)中僅指定了6個(gè)字節(jié)。
4 第37到第42行檢測(cè)并報(bào)告可能發(fā)生的錯(cuò)誤,。
5 第44行聲明一個(gè)成功寫(xiě)操作,。
6 在第49行read調(diào)用試著從另一個(gè)套接口s[0]讀取消息。在這條語(yǔ)句中,,可以讀取任何最大為buf[]數(shù)組尺寸的消息,。
7 第50行到第55行檢測(cè)并服務(wù)在read語(yǔ)句中可能發(fā)生的錯(cuò)誤。
8 第60行到第62行報(bào)告一條成功接收的消息,。
9 第67行到第73行向套接口s[0]寫(xiě)入一條回復(fù)消息"Go away!",。這就演示了不同于管道,信息在可以作為端點(diǎn)的套接口中雙向傳送,。
10 第75行聲明一個(gè)成功的寫(xiě)操作,。
11 第80行到第86行應(yīng)從通信線路的另一個(gè)端點(diǎn)套接口s[1]中讀取信息"Go away!"。
12 第91行到第93行報(bào)告成功接收的信息,。
13 這兩個(gè)套接口在第98行和第99行關(guān)閉,。
14 在第102行程序退出。
當(dāng)程序被調(diào)用時(shí),,輸出結(jié)果如下:
$ ./01lst02
Wrote message 'Hello?' on s[1]
Received message 'Hello?' from socket s[0]
Wrote message 'Go away!' on s[0]
Received message 'Go away!' from socket s[1]
Done.
$
如果我們跟蹤我們?cè)谇懊嫠串?huà)的步驟,,我們就會(huì)發(fā)現(xiàn)信息是在套接口中雙向傳送的。而且我們演示了套接口用與文件相同的方式來(lái)關(guān)閉,。
關(guān)閉套接口
在前面,,我們看到如何來(lái)創(chuàng)建一對(duì)套接口,并且看到如何使用這些套接口來(lái)執(zhí)行最基本的輸入與輸出操作,。我們也可以看到套接口可以使用與通過(guò)調(diào)用close函數(shù)來(lái)關(guān)閉文件的方式來(lái)關(guān)閉?,F(xiàn)在我們來(lái)了解一下關(guān)閉套接口所提供的函數(shù)。
當(dāng)從通過(guò)pipe函數(shù)創(chuàng)建的管道中讀取時(shí),,當(dāng)接收到一個(gè)文件結(jié)尾時(shí),,接收就會(huì)認(rèn)為不會(huì)再有要接收的數(shù)據(jù)。當(dāng)關(guān)閉管道的寫(xiě)端時(shí),,文件結(jié)束的條件是通過(guò)寫(xiě)進(jìn)程發(fā)送的,。
同樣的過(guò)程也可以用在套接口上。當(dāng)另一個(gè)端點(diǎn)關(guān)閉時(shí),接收端就會(huì)收到一個(gè)文件結(jié)束的標(biāo)識(shí),。
當(dāng)本地進(jìn)程希望通知遠(yuǎn)程端不再接收數(shù)據(jù)時(shí)就會(huì)出現(xiàn)問(wèn)題,。如果本地進(jìn)程關(guān)閉了他的套接口,這是可以適用的,。然而,,如果他希望從遠(yuǎn)程端接收一個(gè)確認(rèn)信息,這是不可能的,,因?yàn)楝F(xiàn)在他的套接口已經(jīng)關(guān)閉了,。這樣的情況需要一個(gè)半關(guān)閉套接口的方法。
shutdown函數(shù)
下面顯示了shutdown函數(shù)的概要:
#include <sys/socket.h>
int shutdown(int s, int how);
shutdown函數(shù)需要兩個(gè)參數(shù),。他們是:
套接口描述符s指定了要部分關(guān)閉的套接口,。
參數(shù)how指定要如何關(guān)閉這個(gè)套接口中。
如果函數(shù)成功則返回0,。如果調(diào)用失敗則會(huì)返回-1,錯(cuò)誤原因?qū)?huì)發(fā)送到errno,。
how的可能值如下:
值    宏        描述
0    SHUT_RD        在指定的套接口上不再允許讀操作。
1    SHUT_WR        在指定的套接口上不再允許寫(xiě)操作,。
2    SHUT_RDWR    在指定的套接口上不再允許讀寫(xiě)操作,。
注意當(dāng)how值指定為2時(shí),這個(gè)函數(shù)的調(diào)用與close函數(shù)調(diào)用相同,。
關(guān)閉向一個(gè)套接口的寫(xiě)
下面的代碼演示了如何指定在本地的套接口上不再執(zhí)行寫(xiě)操作:
int z;
int s;  /* Socket */
z = shutdown(s, SHUT_WR);
if ( z == -1 )
    perror("shutdown()");
關(guān)閉套接口的寫(xiě)端解決了一系列難題,。他們是:
清空包含任何要發(fā)送的數(shù)據(jù)的內(nèi)核緩沖區(qū)。通過(guò)內(nèi)核網(wǎng)絡(luò)軟件來(lái)緩沖數(shù)據(jù)來(lái)改進(jìn)性能,。
向遠(yuǎn)程套接口發(fā)送文件結(jié)束標(biāo)識(shí),。這就通知遠(yuǎn)程讀進(jìn)程在這個(gè)套接口上不會(huì)再向他發(fā)送數(shù)據(jù)。
保留半關(guān)閉套接口為讀打開(kāi),。這就使得在套接口上發(fā)送了文件結(jié)束標(biāo)識(shí)以后還可以接收確認(rèn)信息,。
丟棄在這個(gè)套接口上的打開(kāi)引用計(jì)數(shù)。只有最后在這個(gè)套接口上的close函數(shù)將會(huì)發(fā)送一個(gè)文件結(jié)束標(biāo)識(shí),。
處理復(fù)制的套接口
如果一個(gè)套接口文件描述符通過(guò)dup或者是dup2函數(shù)來(lái)調(diào)用進(jìn)行復(fù)制,,只有最后的close函數(shù)調(diào)用可以關(guān)閉這個(gè)套接口,。這是因?yàn)榱硗鈴?fù)制的文件描述符仍處于使用狀態(tài),。如下面的代碼如演示的樣子:
int s;      /* Existing socket */
int d;      /* Duplicated socket */
d = dup(s); /* duplicate this socket */
close(s);   /* nothing happens yet */
close(d);   /* last close, so shutdown socket */
在這個(gè)例子中,第一個(gè)close函數(shù)調(diào)用不會(huì)有任何效果,。先關(guān)閉其中的任何一個(gè)都是一樣的結(jié)果,。關(guān)閉s或者d將會(huì)為同一個(gè)套接口保留一個(gè)文件描述符。只有通過(guò)close函數(shù)調(diào)用來(lái)關(guān)閉最后一個(gè)存在的文件描述符才會(huì)有效果,。在這個(gè)例子中,,關(guān)閉d文件描述符關(guān)閉了這個(gè)套接口。
shutdown函數(shù)避免了這種區(qū)別。重復(fù)這個(gè)例子代碼,,通過(guò)使用shutdown函數(shù)解決了這個(gè)問(wèn)題:
int s;        /* Existing socket */
int d;        /* Duplicated socket */
d = dup(s);   /* duplicate this socket */
shutdown(s,SHUT_RDWR); /* immediate shutdown */
盡管套接口s也在文件單元d上打開(kāi),,shutdown函數(shù)立刻使得套接口執(zhí)行關(guān)閉操作。這個(gè)操作在打開(kāi)的文件描述符s和d都是同樣的效果,,因?yàn)樗麄冎赶蛲粋€(gè)套接口,。
這個(gè)問(wèn)題出現(xiàn)的另一個(gè)方式就是執(zhí)行了fork函數(shù)調(diào)用。任何優(yōu)先級(jí)高于fork操作的套接口都會(huì)在子進(jìn)程中被復(fù)制,。
關(guān)閉從一個(gè)套接口讀
關(guān)閉套接口的讀取端將會(huì)使得待讀取的任何數(shù)據(jù)都會(huì)被忽略掉,。如果從遠(yuǎn)程套接口發(fā)送來(lái)更多的數(shù)據(jù),也同樣會(huì)被忽略掉,。然而任何試著從這個(gè)套接口進(jìn)行讀取的進(jìn)程都會(huì)返回一個(gè)錯(cuò)誤,。這通常用來(lái)強(qiáng)制協(xié)議或是調(diào)試代碼。
shutdown函數(shù)的錯(cuò)誤代碼如下:
錯(cuò)誤        描述
EBADF        指定的套接口不是一個(gè)可用的文件描述符
ENOTSOCK    指定的文件描述符不是一個(gè)套接口
ENOTCONN    指定的套接口并沒(méi)有連接
從這個(gè)表中我們可以看到,,對(duì)于已連接的套接口應(yīng)只調(diào)用shutdown函數(shù),,否則就會(huì)返回ENOTCONN錯(cuò)誤代碼。
編寫(xiě)一個(gè)客戶/服務(wù)器例子
現(xiàn)在我們所了解的套接口API的集合已經(jīng)足夠讓我們開(kāi)始一些有趣的嘗試了,。在這一部分,,我們會(huì)檢測(cè),編譯并且測(cè)試一個(gè)簡(jiǎn)單的通過(guò)套接口進(jìn)行通信的客戶與服務(wù)器進(jìn)程,。
為了使得這個(gè)程序盡可能的小,,將會(huì)啟動(dòng)一個(gè)程序,然后復(fù)制為一個(gè)客戶進(jìn)程與一個(gè)服務(wù)器進(jìn)程,。子進(jìn)程將會(huì)是客戶端程序角色,,而原始的父進(jìn)程將會(huì)執(zhí)行服務(wù)器的角色。下圖顯示了父進(jìn)程與子進(jìn)程的關(guān)系以及套接口的使用,。

父進(jìn)程是最初啟動(dòng)的程序,。他立刻通過(guò)調(diào)用socketpair函數(shù)來(lái)生成一對(duì)套接口,然后通過(guò)調(diào)用fork函數(shù)將自己復(fù)制為兩個(gè)進(jìn)程,。
服務(wù)器將會(huì)接收請(qǐng)求,,執(zhí)行請(qǐng)求,然后退出,。類似的客戶端將會(huì)執(zhí)行請(qǐng)求,,報(bào)告服務(wù)器響應(yīng),然后退出,。
請(qǐng) 求將會(huì)采用strftime函數(shù)的第三個(gè)參數(shù)的格式,。這是一個(gè)用來(lái)格式化日期與時(shí)間字符串的格式字符串。服務(wù)器將會(huì)在接收到請(qǐng)求時(shí)得到當(dāng)前的日期與時(shí)間,。 服務(wù)器將會(huì)使用客戶端的請(qǐng)求字符串來(lái)將其格式化為最終的字符串,,然后發(fā)送給客戶端。我們先來(lái)回顧一個(gè)strftime函數(shù)的概要:
#include <time.h>
size_t strftime(char *buf,
    size_t max,
    const char *format,
    const struct tm *tm);
參數(shù)buf與max分別指定了輸出緩沖區(qū)以及最大長(zhǎng)度。參數(shù)format是一個(gè)輸入字符串,,可以允許我們來(lái)格式化日期與時(shí)間字符串,。最后參數(shù)tm用來(lái)指定必須來(lái)創(chuàng)建輸出日期與時(shí)間字符串的日期與時(shí)間組件。
/*****************************************
 *
 * Listing 1.3
 *
 * Client/Server Example Using socketpair
 * and fork:
 *
 * ******************************************/

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/wait.h>
#include <time.h>

/*
 * As of RedHat 6.0,these are still not defined:
 */
#ifndef SHUT_WR
#define SHUT_RD 0
#define SHUT_WR 1
#define SHUT_RDWR 2
#endif

/*
 * Main program
 */
int main(int argc,char **argv)
{
    int z;        /* Status return code */
    int s[2];    /* Pair of sockets */
    char *msgp;    /* A message pointer */
    int mlen;    /* Message length */
    char buf[80];    /* work buffer */
    pid_t chpid;    /* Child PID */

    /*
     * Create a pair of local sockets:
     */
    z = socketpair(AF_LOCAL,SOCK_STREAM,0,s);
    if(z == -1)
    {
        fprintf(stderr,"%s:socketpair(2)\n",strerror(errno));
        exit(1);
    }

    /*
     * Now fork() into two processes:
     */
    if((chpid = fork()) == (pid_t)-1)
    {
        /*
         * Failed to fork into two processes:
         */
        fprintf(stderr,"%s:fork(2)\n",strerror(errno));
        exit(1);
    }
    else if(chpid == 0)
    {
        /*
         * This is child process(client)
         */
        char rxbuf[80];     /*Receive buffer*/
        printf ("Parent PID is %ld\n",(long)getppid());
        close(s[0]);        /* Server uses s[1] */
        s[0] = -1;        /*Forget this unit */

        /*
         * Form the message and its length:
         */
        msgp = "%A %d-%b-%Y %l:%M %p";
        mlen = strlen(msgp);

        printf("Child sending request '%s'\n",msgp);
        fflush(stdout);

        /*
         * Write a request to the server:
         */

        z = write(s[1],msgp,mlen);
        if(z<0)
        {
            fprintf(stderr,"%s:write(2)\n",strerror(errno));
            exit(1);
        }

        /*
         * Now indicate that we will not be writing
         * anything further to our socket,by shutting
         * down the write side of the socket:
         */
        if(shutdown(s[1],SHUT_WR) == -1)
        {
            fprintf(stderr,"%s:shutdown(2)\n",strerror(errno));
            exit(1);
        }

        /*
         * Recevie the reply from the server:
         */
        z = read(s[1],rxbuf,sizeof rxbuf);
        if(z<0)
        {
            fprintf(stderr,"%s:read(2)\n",strerror(errno));
            exit(1);
        }

        /*
         * Put a null byte at the end of what we
         * received from the server:
         */
        rxbuf[z]=0;

        /*
         * Report the result:
         */
        printf("Server returned '%s'\n",rxbuf);
        fflush(stdout);
        close(s[1]);    /*Close our end now*/
    }
    else
    {
        /*
         * This is parent process(server):
         */

        int status;    /*Child termintation status*/
        char txbuf[80];    /*Reply buffer*/
        time_t td;    /*Current date&time*/
        printf("Child PID is %ld\n",(long)chpid);
        fflush(stdout);

        close(s[1]);    /* Cient uses s[0] */
        s[1] = -1;    /* Forget this desciptor */

        /*
         * Wait for a request from the client:
         */
        z = read(s[0],buf,sizeof buf);
        if(z<0)
        {
            fprintf(stderr,"%s:read(2)\n",strerror(errno));
            exit(1);
        }
        /*
         * Put a null byte at the end of the
         * message we recevied from the client:
         */
        buf[z] = 0;

        /*
         * Now perform the server function on
         * the received message
         */
        time(&td);    /* Get current time */
        strftime(txbuf,sizeof txbuf,    /* Buffer */
                buf,        /* Input fromate*/
                localtime(&td));/* Input time */
        /*
         * Send back the response to client:
         */
        z = write (s[0],txbuf,strlen(txbuf));
        if(z<0)
        {
            fprintf(stderr,"%s:write(2)\n",strerror(errno));
            exit(1);
        }
        /*
         * Close our end of the socket
         */
        close(s[0]);

        /*
         * Wait for the child process to exit:
         */
        waitpid(chpid,&status,0);

    }
    return 0;
}

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,,所有內(nèi)容均由用戶發(fā)布,,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式,、誘導(dǎo)購(gòu)買等信息,,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,,請(qǐng)點(diǎn)擊一鍵舉報(bào),。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多