linux网络编程简单C/S模型实现

Talk is cheap,show me the code

server.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h> //类unix系统中,对系统调用的封装接口
                    //如提供通用的文件、目录、程序、及进程操作的函数
#include <errno.h> //提供错误号error定义,用于错误处理
#include <sys/socket.h> //提供socket函数及数据结构
#include <sys/types.h> //数据类型定义
#include <netinet/in.h> //定义数据结构sockaddr_in
#include <arpa/inet.h> //提供IP地址转换函数

#define MAXLINE 255 //最大接受字节数

/*一切皆socket*/
/*socket套接字概念介绍*/
/*Unix/Linux基本哲学:“一切皆文件”
 * Socket就是该模式的实现,是一种特殊的文件
 * 一些socket函数就是对其进行操作,如读写,打开,关闭
 * socket为应用层与TCP/IP协议族通信的中间软件抽象层,是一组接口
 * 让socket去组织数据,以符合指定的协议*/

int main(int argc,char** argv)
{
    int lis_fd,con_fd; //套接字描述符
    /*其实为一个整数,如所熟悉的0、1、2对应的FILE*结构为stdin、stdout、stderr
     * 记录操作系统函数返回的一个整数作为描述符来标识套接字socket
     * 接着,再以此描述符作为传递参数,调用函数完成某种操作*/

    struct sockaddr_in serv_addr,clit_addr; //IPV4地址结构
    socklen_t clit_len;
    char buf[MAXLINE]={0}; //缓冲区
    int i,n,port;

    if(argc<3){
        printf("please fill the parameter\n");  
        return 1;
    }
    //服务器端开始建立监听socket描述符,唯一标识一个socket
    //第一个参数protofamily协议域、二type指定socket类型、三protocol指定协议
    //返回socket描述字符位于协议族空间中,但无具体的地址
    //通过bind函数赋予地址,或connect/listen时随机分配
    if(-1 == (lis_fd=socket(AF_INET,SOCK_STREAM,0))){
        perror("socket error\n");
        exit(1);
    }
    //初始化
    bzero(&serv_addr,sizeof(serv_addr)); 
    //memset(&serv_addr,0,sizeof(serv_addr));

    //服务器填充sockaddr结构
    serv_addr.sin_family=AF_INET; //设置地址类型 IPV4
    //serv_addr.sin_addr.s_addr=htonl(INADDR_ANY); //设置IP地址,让系统自动获取本机IP地址
    serv_addr.sin_addr.s_addr=inet_addr(argv[1]);
    port=atoi(argv[2]);
    serv_addr.sin_port=htons(port); //设置默认端口号

    //函数bind将服务器的本地地址和套接字绑定
    if(-1==bind(lis_fd,(struct sockaddr*)&serv_addr,sizeof(struct sockaddr))){
        perror("bind error\n"); 
        exit(1);
    }
    //listen函数提醒内核,此套接字可接受客户端请求,开始监听
    if(listen(lis_fd,10)==-1){ //第二个参数为socket可排队的最大连接数
        perror("listen error\n");   
        exit(1);
    }   

    printf("========waiting for client's request===========\n");

    /*处理客户端请求,通过accept函数获得与一个客户端的连接*/
    clit_len=sizeof(struct sockaddr_in); 
    //accept返回的是已连接socket套接字描述符,不同于之前的监听描述符,且默认阻塞进程
    if(-1==(con_fd=accept(lis_fd,(struct sockaddr*)&clit_addr,&clit_len))){
        perror("accept error\n");   
        exit(1);
    }
    printf("connect from %s:%u...!\n",inet_ntoa(clit_addr.sin_addr),ntohs(clit_addr.sin_port));

    while(1){ 
        //接受客户端发送来的数据
        memset(buf,0,MAXLINE);
        if((n=recv(con_fd,buf,MAXLINE,0))==0){
            sleep(1); //linux的sleep默认睡1秒
            continue;
        }

        buf[n]=0;
        printf("recv msg from client: %s\n",buf);
        if(0 == strncmp(buf,"quit",4)){
            break;
        }
        if(0 == strncmp(buf,"send",4)){
            memset(buf,0,MAXLINE);
            scanf("%s",&buf);   
            send(con_fd,buf,strlen(buf),0);
        }
    }
    close(con_fd);
    close(lis_fd);
    exit(0);
}
client.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>

#define MAXLINE 255

int main(int argc,char** argv)
{
    int sockfd,n,rec_len,port;
    char recvline[MAXLINE],sendline[MAXLINE];
    struct sockaddr_in conn_addr;
    if(argc<3){
        printf("please fill the parameter\n");  
        return 1;
    }
    //if(sockfd=socket(AF_INET,SOCK_STREAM,0)<0){
    //优先级问题,sockfd接受比较后的01,没有得到正确的描述符
    //找了一晚上的bug。。。心态大崩
    //大家以后以此为戒,勤加括号,避免粗心大意
    if((sockfd=socket(AF_INET,SOCK_STREAM,0))<0){
        perror("socket error\n");   
        exit(1);
    }
    bzero(&conn_addr,sizeof(conn_addr));
    conn_addr.sin_family=AF_INET;
    port=atoi(argv[2]); //端口号,字符串转换至整型
    conn_addr.sin_port=htons(port);
    conn_addr.sin_addr.s_addr=inet_addr(argv[1]);
    /*
    if(inet_pton(AF_INET,argv[1],&conn_addr.sin_addr)<=0){ //转换字符串到网络地址
        printf("exchange error\n"); 
        exit(1);
    }*/
    if(connect(sockfd,(struct sockaddr*)&conn_addr,sizeof(conn_addr))<0){
        printf("connect error: %s(error: %d)\n",strerror(errno),errno);
        exit(1);
    }

    printf("send msg to server: \n");
    while(1){
        memset(sendline,0,MAXLINE);
        fgets(sendline,MAXLINE,stdin);
        if(send(sockfd,sendline,strlen(sendline),0)<0){
            printf("send error\n"); 
            exit(1);
        }
        memset(recvline,0,MAXLINE);
        if((rec_len=recv(sockfd,recvline,MAXLINE,0))==-1){
            printf("recv error\n");
            exit(1);    
        }
        recvline[rec_len]='\0';
        if(0 == strncmp(recvline,"quit",4)) break;
        printf("Received: %s\n",recvline);
    }
    close(sockfd);
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值