首页 > 代码库 > unix网络编程之回射

unix网络编程之回射

//client.cpp
//这是回射客户端
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <netinet/in.h>
#include <string.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <errno.h>

#define SA struct sockaddr

//readline函数
int readline(int fd,char *buf,int sizeline)
{
    printf("我已进入readline\n");
    //字符串处理问题
    //思考在这里为什么重新定义一个ptr指针??
    char c,*ptr;
    ptr=buf;
    int n;
    again:
    while((n=read(fd,&c,1))>0)
    {
        *ptr++=c;
        if(c==0){       //note  difference 0 ‘\0‘  NULL ‘0‘
            // it‘s means it up to end the string
            break;
        }
    }
    if(n<0 && errno==EINTR)
    {
        goto again;
    }else if(n<0)
    {
        printf("read出错%s\n",strerror(errno));
    }
    return 0;
}

//字符回显函数
int str_cli(FILE *f,int fd){
char sendbuf[20],recvbuf[20];

    while(fgets(sendbuf,20,f)!=NULL)
    {
        sendbuf[strlen(sendbuf)+1]=0;
        if( write(fd,sendbuf,strlen(sendbuf)+1)<0)
        {
            printf("str_cli write 出现错误%s\n",strerror(errno));
            exit(0);
        }
        printf("send buf is %s%d",sendbuf,strlen(sendbuf));
        bzero(sendbuf,20);
        readline(fd,recvbuf,20);
        fputs(recvbuf,stdout);
    }//end while
    return 0;
}
/*
    在这里我们将服务器的ip地址我们手动输入
    1.创建socket
    2.connnect
*/

int main(int argc,char **argv)
{
    if(argc<2)
    {
            printf("请输入合理的参数\n");
            exit(0);
    }

    int listenfd;
    struct  sockaddr_in cliaddr;
    //create socket
    listenfd=socket(AF_INET,SOCK_STREAM,0);
    if(listenfd<0)
    {
        printf("创建socket出错%s\n",strerror(errno));
        exit(0);
    }

    //connect   在这里我们将使用inet_pton来配置ip
    bzero(&cliaddr,sizeof(cliaddr));
    cliaddr.sin_family=AF_INET;
    cliaddr.sin_port=htons(9877);
    if(inet_pton(AF_INET,argv[1],&cliaddr.sin_addr)<0)
    {
        printf("inet_pton出现错误%s\n",strerror(errno));
        exit(0);
    }
    if(connect(listenfd,(SA *)&cliaddr,sizeof(cliaddr))<0)
    {
            printf("connect 出现错误%s\n",strerror(errno));
            exit(0);
    }
    printf("我已经成功连接服务器\n");
    //向服务器发送数据和回显数据
    str_cli(stdin,listenfd);
    exit(0);
    return 0;
}


//server.cpp
//这个是回射服务器程序

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <netinet/in.h>
#include <string.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <errno.h>

#define SA struct sockaddr

//回射函数
//从fd读然后写向fd
int str_echo(int fd){
    printf("进入str_echo\n");
    char buf[20];
    int n;
    int myread;
    again:
    bzero(buf,20);
    while( (myread=read(fd,buf,20)) > 0){
       // buf[myread]=0;
        if( (n=write(fd,buf,myread))<0)
        {
            printf("写出现错误\n");
            exit(0);
        }
         printf("server写完%d%s\n",n,buf);
         bzero(buf,20);
        //如果在读的过程中出现错误 那么将相应处理之
    }//end while
    printf("end while?????\n");
    if(myread<0&&errno==EINTR)      //忽略
        {
            printf("ooops\n");
            goto again;
        }else if(myread<0)
        {
            printf("读出现错误%s\n",strerror(errno));
            exit(0);
        }else if(myread==0)
        {
            printf("ooooo返回0\n");
        }
        return 0;
}

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

     int  listenfd,connfd;
     socklen_t cliins;
     pid_t childpid;
     struct sockaddr_in serin,cliin;

    /*
        1.创建socket
        2.bind (sockaddr_in的相关初始化)
        3.listen
        4.accpet
    */
    listenfd=socket(AF_INET,SOCK_STREAM,0);     //在服务器中往往只创建一个listenfd套接字
    if(listenfd<0){                                                   //他将会在全局存在
        printf("socket创建失败%s\n",strerror(errno));
        exit(0);
    }

    bzero(&serin,sizeof(serin));
    serin.sin_family=AF_INET;
    serin.sin_port=htons(9877);
    serin.sin_addr.s_addr=htonl(INADDR_ANY);
    //bind
    if(bind(listenfd,(SA *)&serin,sizeof(serin))<0)
    {
        printf("bind创建失败%s\n",strerror(errno));
        exit(0);
    }

    //listen
    listen(listenfd,5);

    //accpet
    //note this 我们传入cliins的值
    cliins=sizeof(cliin);
    //在这里我们将fork一个进程来接收新的请求
    for(;;){
      connfd=accept(listenfd,(SA *)&cliin,&cliins);
       if(connfd<0){
                printf("accpet 创建失败%s\n",strerror(errno));
                exit(0);
            }
      printf("链接已经建立\n");
        if((childpid=fork())<0)
        {
            printf("创建进程失败\n");
            exit(0);
        }else if(childpid==0)
        {
            //child
            printf("子进程已建立\n");
            close(listenfd);
            //调用回显函数
            str_echo(connfd);
            printf("子进程已做相关处理\n");
            exit(0);
        }
        //parent
        close(connfd);
    }// end for
    return 0;
}

/////////////////////////////////////////////////////////////////note////////////////////////////////////////////////////////////////////////////////
我们在这里需要注意的是相关IO的处理问题
比如说char a[50];
当我第一次写a="www.baidu.com"
第二次写如数据www.sina.com若最后没有添加0或‘\0’或NULL 那么他将只会覆盖前面几个字符 然后一直读到www.baidu.com的0处


unix网络编程之回射