网络服务器开发实战练习(2)——回声服务器实现

1.项目需求

实现回声服务器的客户端服务器程序,客户端通过网络连接到服务器,并发送任意一串英文信息,服务器端接受信息后,将每个字符转换为大写并回送给客户端显示。

2.知识准备

(1)网络通信与Socket

本示例来自于动脑学院Martin老师的免费课程

例子:90年代的通信

寄信者:                                                                           

写好要发送的地址

还要写好相应的姓名,因为接受地址有很多人,到底属于谁接收就需要姓名来区分

然后放到邮筒中就可以

邮局:

传输信件

接受者:

由于信件比较多,小区让每家每户自己准备一个信箱,按图中步骤,最终挂于小区的传达室,传达室有信件来的话保安直接塞到信箱当中,这样信就属于收信者了,随时可以去取,为了能够接受信,收信者需要时不时来看一下信箱是否有信

Socket通信的三个要素:

通信的目的地址---------------------------------------邮件发送的地址

   IP地址,我们平时的通信都是通过IP地址进行通信的

   比如我们在浏览器中输入www.baidu.com,其实访问的是服务器,浏览器会首先查询域名对应的IP地址,我们可以通过 nslookup 域名 来查询域名对应的IP地址

    每台主机的IP地址都是唯一的

端口号---------------------------------------------收件人的姓名

因为每台服务器可能安装了很多应用,我们到底要把数据传给哪个应用,就需要通过端口区分

http协议默认端口:80  (给http服务器用)       SMTP协议默认端口:25(给邮件服务器用)

使用的传输层协议

 TCP、UDP

而Socket就像上述例子中的邮筒

(2)Socket通信模型

不管是客户端还是服务器端,都会有自己的操作系统,而操作系统已经帮我们封装好了数据链路层,网络层和传输层的具体通信的细节都实现了封装,电信等ISP已经帮我们做好了物理层,于是客户端和服务器端通信的过程就是建立Socket的过程。

3.项目代码(待完善与测试)

服务器端代码:echo_server.c

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>  //网络的库
#include <string.h>
#include <ctype.h>    //类型的定义
#include <arpa/inet.h>   //地址转换

//IP地址
#define IP "0.0.0.0"

//定义端口
#define SERVER_PORT 888

perror_exit(const char * des){
    fprintf(stderr, "%s error, reason: %s\n", des, strerror(errno));
    //perror(des);
    exit(1);
}

int main(void)
{
	int sock;//代表信箱
        int i, ret;
	struct sockaddr_in server_addr;  //服务器的地址

	//1.美女创建信箱
	sock =  socket(AF_INET,SOCK_STREAM,0);//作用:创建套接字  第一个参数:网络通信家族  第二个参数:
使用TCP协议  第三个参数:一般填0

        if(sock == -1){
            perror_exit("create socket");
        }

	//2.清空标签,写上地址和端口号
	bzero(&server_addr,sizeof(server_addr)); //把整个结构体清零
	
	server_addr.sin_family =AF_INET;//选择协议族IPV4
	server_addr.sin_addr.s_addr = htonl(INADDR_ANY);//监听本地所有IP地址,hton1是把字节顺序进行调整,把机器上的字节顺序调整为网络上的字节顺序
	server_addr.sin_port =htons(SERVER_PORT);//绑定端口号,htons也是把主机字节顺序转变成网络字节顺序
	
	//实现标签贴到信箱
	ret=bind(sock,(struct sockaddr*)&server_addr,sizeof(server_addr));

        if(ret == -1){
            perror_exit("bind");
        }
	
	//128同一时刻允许向客户端发起连接的数量
	//把信箱挂载到传达室,这样就可以接信了
	ret=listen(sock,128);

        if(ret == -1){
            perror_exit("listen");
        }
	
	printf("等待客户端的连接\n");

	//服务器一直等等待接受来信
	int done = 1;
    while(done){
        struct sockaddr_in client;
        int client_sock, len;
        char client_ip[64];
        char buf[256];

        socklen_t  client_addr_len;
        client_addr_len = sizeof(client);
        client_sock = accept(sock, (struct sockaddr *)&client, &client_addr_len);

        //打印客服端IP地址和端口号
        printf("client ip: %s\t port : %d\n",
                 inet_ntop(AF_INET, &client.sin_addr.s_addr,client_ip,sizeof(client_ip)),
                 //把网络字节序转换成字符串类型
                 ntohs(client.sin_port));
        /*读取客户端发送的数据*/
        len = read(client_sock, buf, sizeof(buf)-1);
        buf[len] = '\0';
        printf("recive[%d]: %s\n", len, buf);

        //转换成大写
        for(i=0; i<len; i++){
            /*if(buf[i]>='a' && buf[i]<='z'){
                buf[i] = buf[i] - 32;
            }*/
            buf[i] = toupper(buf[i]);
        }

        len = write(client_sock, buf, len);
        printf("write finished. len: %d\n", len);
        close(client_sock);

    }

}

步骤总结:

(1)创建服务器的socket

(2)创建服务器地址包括IP地址和端口号以及使用的协议族

(3)将socket和服务器地址绑定到一起

(4)监听端口

(5)接收客户端通信

(6)处理客户端请求

客户端:

//客户端
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>

#define SERVER_PORT 666
#define SERVER_IP  "127.0.0.1"

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

    int sockfd;
    char *message;
    struct sockaddr_in servaddr;
    int n;
    char buf[64];

    if(argc != 2){
        fputs("Usage: ./echo_client message \n", stderr);
        exit(1);
    }

    message = argv[1];

    printf("message: %s\n", message);

    sockfd = socket(AF_INET, SOCK_STREAM, 0);

    memset(&servaddr, '\0', sizeof(struct sockaddr_in));

    servaddr.sin_family = AF_INET;
    inet_pton(AF_INET, SERVER_IP, &servaddr.sin_addr);
    servaddr.sin_port = htons(SERVER_PORT);

    connect(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr));

    write(sockfd, message, strlen(message));

    n = read(sockfd, buf, sizeof(buf)-1);

    if(n>0){
        buf[n]='\0';
        printf("receive: %s\n", buf);
    }else {
        perror("error!!!");
    }

    printf("finished.\n");
    close(sockfd);

    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_34805255/article/details/84344738