unix下实现echo机制

29 篇文章 0 订阅

linux下的echo命令:

echo命令的功能是在显示器上显示一段文字,一般起到一个提示的作用。
该命令的一般格式为: echo [ -n ] 字符串
其中选项n表示输出文字后不换行;字符串能加引号,也能不加引号。用echo命令输出加引号的字符串时,将字符串原样输出;用echo命令输出不加引号的字符串时,将字符串中的各个单词作为字符串输出,各字符串之间用一个空格分割。

功能说明:显示文字。
语   法:echo [-ne][字符串]或 echo [--help][--version]
补充说明:echo会将输入的字符串送往标准输出。输出的字符串间以空白字符隔开, 并在最后加上换行号。
参   数:-n 不要在最后自动换行
-e 若字符串中出现以下字符,则特别加以处理,而不会将它当成一般
文字输出:
 

  \a 发出警告声;
 
  \b 删除前一个字符;
 
  \c 最后不加上换行符号;
 
  \f 换行但光标仍旧停留在原来的位置;
 
  \n 换行且光标移至行首;
 
  \r 光标移至行首,但不换行;
 
  \t 插入tab;
 
  \v 与\f相同;
 
  \\ 插入\字符;
 
  \nnn 插入nnn(八进制)所代表的ASCII字符;
–help 显示帮助
–version 显示版本信息


源代码如下:

客户端:

//this is the client of the echo 
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>

#define UNIX_SOCK_PATH "/tmp/my_unix_socket"

int main(int argc,char *argv[])
{
   int conn_fd,serv_len;
   struct sockaddr_un serv_addr;
   int ret;
   char send_line[100],recv_line[100];
   
   conn_fd=socket(AF_UNIX,SOCK_STREAM,0);
   bzero(&serv_addr,sizeof(serv_addr));
   serv_addr.sun_family=AF_UNIX;
   strcpy(serv_addr.sun_path,UNIX_SOCK_PATH);
   serv_len=strlen(serv_addr.sun_path)+sizeof(serv_addr.sun_family);
   ret=connect(conn_fd,(struct sockaddr *)&serv_addr,serv_len);
   if(ret==-1)
   { 
      perror("client connect failed!\n");
      exit(1);
   }
   while(1)
   {
      if(fgets(send_line,100,stdin)==NULL)
          {
             printf("receives end of the file\n");
             exit(0);
          }
       else{
              sendagain:
                ret=send(conn_fd,send_line,strlen(send_line),0);
                if(ret<0 && errno!=EINTR)
                  {
                    perror("send failed\n");
                    exit(1);
                  }
                else if(ret<0&&errno==EINTR) //EINTR which means the send interuputd by signal
                   goto sendagain;           //so you should try it again
               recvagain:
                 ret=recv(conn_fd,recv_line,100,0);
                if(ret<0 && errno!=EINTR)
                  {
                    perror("recv failed\n");
                    exit(1);
                  }
                else if(ret<0&&errno==EINTR)
                   goto recvagain;
               if(ret==0)
                 {
                    fprintf(stderr,"peer close the connection.\n");
                    exit(0);
                 }
               if(ret>0)
                 {
                    recv_line[100]='\0';
                    fprintf(stdout,recv_line);
                 }
            }
   }
   exit(0);
}

服务器端:

//this is the server of the echo 
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <signal.h>
#include <sys/wait.h>
#include <unistd.h>
#define LISTENQ 10
#define UNIX_SOCK_PATH "/tmp/my_unix_socket"
/*
struct sockaddr_un
           {
              short int sun_family;
              char sun_path[104];
           };
*/
void echo_service(int conn_fd);
int main(int argc,char ** argv)
{
   int listen_fd,conn_fd;
   int serv_len,cli_len;
   pid_t chld_pid;
   struct sockaddr_un cli_addr,serv_addr;
   int ret;
   int re_use_addr=1;
   int fd;
   int link;
   listen_fd=socket(AF_UNIX,SOCK_STREAM,0);
   if(listen_fd==-1)
   {
      printf("create listen_fd failed!\n");
      exit(1);
   }
   serv_addr.sun_family=AF_UNIX;
   strcpy(serv_addr.sun_path,UNIX_SOCK_PATH);
   serv_len=strlen(serv_addr.sun_path)+sizeof(serv_addr.sun_family);
   /*
     the system will create the file which is located in the fixed path, so we should delete the file in that
     path now,this can avoid the bind()function successful used 
   */
   
   unlinkagain:
    link=unlink(serv_addr.sun_path);
    if(link==-1&&errno!=EINTR)
     {
       perror("unlink failed!\n");
       exit(1);
     }
    else if(link==-1&&errno==EINTR)
      {
        goto unlinkagain;
      }
   setsockopt(listen_fd,SOL_SOCKET,SO_REUSEADDR,(void *)&re_use_addr,sizeof(int)); //this function is to reuse the port which the other 
                                                                                   //process used before
   ret=bind(listen_fd,(struct sockaddr *)&serv_addr,serv_len);
   if(ret<0)
   {
      perror("bind server port failed!\n");
      exit(1);
   }
   listen(listen_fd,LISTENQ);
   while(1)
   {
      cli_len=sizeof(cli_addr);
      printf("the server is wanting for accept new connecion\n");
      conn_fd=accept(listen_fd,(struct sockaddr*)&cli_addr,&cli_len);
      if(conn_fd<0 && errno==EINTR)
         continue;
      else if(conn_fd<0)
           { 
               perror("accept socket failed!\n");
               exit(1);
           }
      printf("the server create a new connection.\n");
      if((chld_pid=fork())==0)
        {
           close(listen_fd);
           echo_service(conn_fd);
           exit(0);
        }
      close(conn_fd);
      while(waitpid(-1,NULL,WNOHANG)>0);
      
   }
   
}

void echo_service(int conn_fd)
{
   ssize_t nline;
   char recv_line[100];
   int ret;
   
   while(1)
   {
      nline=recv(conn_fd,recv_line,100,0);
      if(nline<0 && errno!=EINTR)
        {
          perror("recv error in echo service");
          exit(1);
        }
      else if(nline<0 &&errno==EINTR)
             {
                 continue; 
             }
      if(nline==0)
        break;
      if(nline>0)
      {
          recv_line[nline]='\0';
        sendagain:
          ret=send(conn_fd,recv_line,nline,0)  ;
          if(ret<0 && errno!=EINTR)
            {
                perror("send error\n");
                exit(1);
            }
          else if(ret<0 && errno==EINTR)
              goto sendagain;
      }
   }
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值