天天看點

并發伺服器的實作

一、伺服器端:tcpserv01.c

/*************************************************************************
    > File Name: tcpserv01.c
    > Author: zsj
    > Mail: 15623582731.com 
    > Created Time: 2017年08月07日 星期一 16時17分55秒
 ************************************************************************/


#include<unp.h>

int main()
{
int listenfd,connfd;  //建立監聽,連接配接套接字。
pid_t childpid;  //建立子程序。
socklen_t clilen;//定義套接字的長度。

struct sockaddr_in cliaddr,servaddr;//定義 客戶 與伺服器套接字

listenfd=Socket(AF_INET,SOCK_STREAM,);//監聽套接字
bzero(&servaddr,sizeof(servaddr));
servaddr.sin_family=AF_INET;//IPV4協定
servaddr.sin_addr.s_addr=htonl(INADDR_ANY);//傳回32位的IP位址的網絡序。
servaddr.sin_port=htons(SERV_PORT); //傳回16位端口号的網絡序。

Bind(listenfd,(SA*) &servaddr,sizeof(servaddr));//調用bind函數給伺服器指定 一個監聽接口,
和通配位址
Listen(listenfd,LISTENQ);//給監聽套接字維護一個隊列。
for(; ;)
{
clilen=sizeof(clilen);
connfd=Accept(listenfd,(SA*)&cliaddr,&clilen);//傳回一個已連接配接套接字,
二三參數為用戶端ip 接口,以及套接字位址長度。

if((childpid=Fork())==)
{
  Close(listenfd);//子程序關閉監聽套接字
  str_echo(connfd); //在套接字上回射資料
  exit();

}
Close(connfd);

}




}

 str_echo.c
#include<unp.h>

void str_echo(int sockfd)
{
ssize_t n;

char buf[MAXLINE];

again:

while((n=read(sockfd,buf,MAXLINE))>)//read函數從套接字讀取資料,

{
  Writen(sockfd,buf,n);//written函數把其中内容回射給客戶。

  if(n< && errno==EINTR)
      goto again;

  else if(n<)
  {
   err_sys("read error");
  }
}


}



           

二、用戶端:tcpcli01.c

/*************************************************************************
    > File Name: tcpcli01.c
    > Author:zsj
    > Mail: [email protected] 
    > Created Time: 2017年08月07日 星期一 16時40分23秒
 ************************************************************************/

#include<stdio.h>
#include<unp.h>

int main(int argc,char **argv)
{
  int sockfd;

  struct sockaddr_in servaddr;

  if(argc!=2)
      err_quit("usag:tcpcli");

  sockfd=Socket(AF_INET,SOCK_STREAM,0);//建立一個套接字

  bzero(&servaddr,sizeof(servaddr));
  servaddr.sin_family=AF_INET;
  servaddr.sin_port=htons(SERV_PORT);//取得16位端口号的網絡序
  Inet_pton(AF_INET,argv[1],&servaddr.sin_addr);//将輸入的伺服器IP位址轉換成二進制。

  Connect(sockfd,(SA*)&servaddr,sizeof(servaddr));//建立與伺服器的連接配接。

  str_cli(stdin,sockfd);

  exit(0);
}


/*************************************************************************
    > File Name: str_cli.c
    > Author: zsj
    > Mail: [email protected] 
    > Created Time: 2017年08月07日 星期一 16時48分38秒
 ************************************************************************/

#include<stdio.h>
#include<unp.h>

void str_cli(FILE *fp,int sockfd)
{
  char sendline[MAXLINE] ,recvline[MAXLINE];

  while(Fgets(sendline,MAXLINE,fp)!=NULL)
  {
    Writen(sockfd,sendline,strlen(sendline));
    if(Readline(sockfd,recvline,MAXLINE)==0)
        err_quit("str_cli");

    Fputs(recvline,stdout);


  }


}

           

三、程式測試:

[email protected]:~/unp/code$ tcpserv01

[1] 17798

[email protected]:~/unp/code$

netstat -a

激活Internet連接配接 (伺服器和已建立連接配接的)

(1)打開 伺服器後:9877是伺服器端接口,處于監聽狀态。

tcp 0 0 :9877 :* LISTEN

(2)開啟用戶端與伺服器建立連接配接

./tcpcli01 127.0.0.1

           

roto Recv-Q Send-Q Local Address Foreign Address State

tcp 0 0 localhost:56121 localhost:9877 ESTABLISHED //用戶端子程序套接字

tcp 0 0 localhost:9877 localhost:56121 ESTABLISHED //伺服器子程序套接字

tcp 0 0 :9877 :* LISTEN //監聽套接字

(3)鍵入一行,立即得到回射接着終止客戶,立即執行

tcp 0 0 :9877 :* LISTEN

cp 0 0 localhost:56122 localhost:9877 TIME_WAIT

繼續閱讀