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处
时间: 2024-11-05 06:58:25

unix网络编程之回射的相关文章

UNIX网络编程卷1 回射客户程序 TCP客户程序设计范式

本文为senlie原创,转载请保留此地址:http://blog.csdn.net/zhengsenlie 下面我会介绍同一个使用 TCP 协议的客户端程序的几个不同版本,分别是停等版本.select 加阻塞式 I/O 版本. 非阻塞式 I/O 版本.fork 版本.线程化版本.它们都由同一个 main 函数调用来实现同一个功能,即回射程序客户端. 它从标准输入读入一行文本,写到服务器上,读取服务器对该行的回射,并把回射行写到标准输出上. 其中,非阻塞式 I/O 版本是所有版本中执行速度最快的,

【UNIX网络编程(三)】TCP客户/服务器程序示例

上一节给出了TCP网络编程的函数,这一节使用那些基本函数编写一个完成的TCP客户/服务器程序示例. 该例子执行的步骤如下: 1.客户从标准输入读入一行文本,并写给服务器. 2.服务器从网络输入读入这行文本,并回射给客户. 3.客户从网络输入读入这行回射文本,并显示在标准输出上. 用图描述如下: 编写TCP回射服务器程序如下: #include <stdio.h> #include <errno.h> #include <stdlib.h> #include <st

[UNIX网络编程] sun rpc实现的简单echo服务器

RPC的全称是Remote Procedure Call,它能够在本地以函数调用的形式来实现网络操作,让程序员集中关注于业务逻辑,不用关心底层的数据通信. 这里不会详细讲解RPC的原理,而是用一个简单的echo服务器的例子来说明如何使用RPC. 最早实现的RPC是sun rpc,现在它已经移植到了大多数操作系统. 使用RPC,程序员只需要关注客户与服务器之间数据传送的格式以及如何远程过程的定位,客户端如何调用本地函数以调用远程函数,服务器远程过程的实现. 1 客户端与服务器之间数据的交互 客户与

【UNIX网络编程(四)】TCP套接字编程详细分析

引言: 套接字编程其实跟进程间通信有一定的相似性,可能也正因为此,stevens这位大神才会将套接字编程与进程间的通信都归为"网络编程",并分别写成了两本书<UNP1><UNP2>.TCP套接字编程是套接字编程中非常重要的一种,仔细分析,其实它的原理并不复杂.现在就以一个例子来详细分析TCP套接字编程. 一.示例要求: 本节中试着编写一个完成的TCP客户/服务器程序示例,并对它进行深入的探讨.该示例会用到绝大多数的基本函数,未用到但比较重要的函数会在后面的补充上

UNIX网络编程笔记(4)—TCP客户/服务器程序示例

TCP客户/服务器程序示例 这一章信息量开始大起来了,粗略来看它实现了简单的TCP客户/服务器程序,里面也有一些费解的细节. 1.概述 完整的TCP客户/服务器程序示例.这个简单的例子将执行如下步骤的一个回射服务器(这里的回射服务器就是服务简单的把客户端发送的消息返回给客户): 1)客户从标准输入读入一行文本,并写给服务器 2)服务器从网络输入读入这行文本,并回射给客户 3)客户从网络输入读入这行回射文本,并显示在标准输出上 这样实际上就构成了一个全双工的TCP连接. 本章就围绕了这个简单的TC

【unix网络编程第三版】阅读笔记(五):I/O复用:select和poll函数

本博文主要针对UNP一书中的第六章内容来聊聊I/O复用技术以及其在网络编程中的实现 1. I/O复用技术 I/O多路复用是指内核一旦发现进程指定的一个或者多个I/O条件准备就绪,它就通知该进程.I/O复用适用于以下场合: (1) 当客户处理多个描述符(一般是交互式输入或网络套接字),必须适用I/O复用 (2) 当一个客户处理多个套接字时,这种情况很少见,但也可能出现 (3) 当一个TCP服务器既要处理监听套接字,又要处理已连接套接字,一般就要使用I/O复用 (4) 如果一个服务器既要适用TCP,

unix网络编程之基本套接口编程

第一章  套接口编程简介 IPv4套接口地址:"网际套接口地址结构" 通用套接口地址结构: 套接口函数被定义为采用指向通用套接口地址结构的指针,这要求对这些函数的任何调用都必须将指向特定于协议的套接口地址结构的指针类型转换成指向通用套接口地址结构的指针: 套接口地址结构的比较: 值-结果参数: 当把套接口地址结构传递给套接口函数时,总是通过指针来传递的,即传递的是一个指向结构的指针. 1, 从进程到内核传递套接口地址结构有3个函数:bind.connect.sendto,这3个函数的一

unix网络编程各种TCP客户-服务器程序设计实例附环境搭建和编译方法(一)

一,到http://download.csdn.net/detail/ts173383201/4505201去下载源代码,然后解压: 二,cd到你解压后的文件夹下,就是有configure的那个目录下,执行命令./configure: 三,执行cd lib跳到lib目录下,执行make命令,会在上层目录(就是刚才有configure那个目录)生成libunp.a文件 四,复制这个静态库libunp.a到/usr/lib/和/usr/lib64/中; 五,接下来在目录中找到unp.h和config

《UNIX网络编程》入门客户端服务器例子

最近在看<UNIX网络编程>(简称unp)和<Linux程序设计>,对于unp中第一个获取服务器时间的例子,实践起来总是有点头痛的,因为作者将声明全部包含在了unp.h里,导致后面编写代码会对这个头文件造成依赖,而学习不到调用了相应功能之后,应该包含哪些确切的头文件. 再者,我下载了unp.h之后,头文件包含再次产生了其他的依赖缺失,因此便参考了<Linux程序设计>中socket一章的入门例子的头文件包含,并且编译中仍然找不到的包含或者是宏定义在unp.h中搜索并粘贴