网络编程2基础知识与客户端服务器通讯

1.基础知识

0.0.0.0 匹配所有IP地址

A类:

特点:一字节网络号,3字节主机号,网络号第一位为0.

范围:0.0.0.1~126.255.255.255

A类地址最大可用网络数:27 -2(网络号除了第一位全0,匹配所有的IP地址;127为环回地址)

A类地址最大可用主机数“224-2(主机号全为0是网关地址;全为1是广播地址)

IP地址数: 网络数*主机数=2113928964(21亿多)

B类:

特点:2字节网络号,2字节主机号,网络号前两位为10.

范围:128.0.0.0~191.255.255.255

B类地址最大可用网络数:214 -1(网络号除了前两位全0,匹配所有的IP地址)

B类地址最大可用主机数“216-2(主机号全为0是网关地址;全为1是广播地址)

IP地址数: 网络数*主机数=1073643522(10亿多)

C类:

特点:3字节网络号,1字节主机号,网络号前两位为110.

范围:192.0.0.0~223.255.255.255

C类地址最大可用网络数:221 -1(网络号除了前三位全0,匹配所有的IP地址)

C类地址最大可用主机数“28-2(主机号全为0是网关地址;全为1是广播地址)

IP地址数: 网络数*主机数=532676354(5亿多)

192.168.2.0/24 (24)指网络号的位数

子网掩码:求出IP地址的网络号或者主机号

子网掩码 & IP地址 = 网络号

~子网掩码 & IP地址 = 主机号

255.255.255.0(C类地址,3位网络号,1位主机号)

协议:双方的约定

常见的协议

(http超文本传输信息),FTP(文件传输协议)

TCP(传输控制协议),UDP(用户数据报协议)

ip(网间协议)

ARP(地址解析协议 IP地址--->mac地址)

RARP(反地址解析协议 mac地址--->IP地址)

协议可以不遵守,但是不安全

封包与拆包的过程:协议+层次结构

数据封包与拆包由操作系统完成

端口号1~1023(1~255之间为众所周知端口,256~1023端口通常由UNIX系统占用)

已登记端口:2014~49151

动态或私有端口:49152~65535

计算机一般是小端存储,网络字节序一般是大端存储

端口号转换

htonl: host to network long

htons: host to network short

ntohl: network to host long

ntohs: host to network short

IP地址转换

inet_addr:IP to network

inet_ntoa:network to IP

作业:

        

1.先关客户端,服务器会一直打印

2.关闭客户端之后,在连接,会显示地址还存在

3.客户端发送一个字符串,服务器返回字符串的长度给客户端

sprintf(buf,"%d",strlen(buf));

4.实现一个时间服务器,客户端发送time,服务器返回当前时间

5.客户端发送get 1.txt的请求,服务器获取文件内容后,发送给客户端。

服务器:

/*===============================================
 *   文件名称:server.c
 *   创 建 者:     
 *   创建日期:2022年08月16日
 *   描    述:
 ================================================*/
#include <stdio.h>
#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <unistd.h>
#include <string.h>
#include <time.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>



int main(int argc, char *argv[])
{ 
    //1.创建监听套接字
    int sockfd = socket(AF_INET,SOCK_STREAM,0);
    if(sockfd <0)
    {
        perror("sockfd");
        return -1;
    }
    
    //端口复用函数
    int on=1;
    int k=setsockopt(sockfd,SOL_SOCKET,SO_REUSEADDR,&on,sizeof(on));
    if(k<0)
    {
    	perror("setsockopt");
    	return -1;
    }
    
    
    //2.绑定服务器的IP地址与端口号
    struct sockaddr_in ser;
    ser.sin_family=AF_INET;
    ser.sin_port=htons(8888);
    //ser.sin_addr.s_addr=inet_addr("0.0.0.0");//"0"表示本机的所有ip
    ser.sin_addr.s_addr=htonl(INADDR_ANY);//"0"表示本机的所有ip
    int ret= bind(sockfd,(struct sockaddr *)&ser,sizeof(ser));
    if(ret<0)
    {
        perror("bind");
        return -1;
    }
    //3.监听
    if(listen(sockfd,10))//最大数量<1024-3
    {
        perror("listen");
        return  -1;
    }

    //4.等待客户端连接,返回通讯套接字(connfd)

    while(1)
    {
        struct sockaddr_in cli;//创建结构体接收客户顿的内容
        int len=sizeof(cli);
        printf("wait a client\n");
        int connfd = accept(sockfd,(struct sockaddr *)&cli,&len);//如果不关心客户端的地址,可以填NULL
        if(connfd<0)
        {
            perror("accept");
            return -1;
        }
        printf("client ip=%s client port=%d\n",inet_ntoa(cli.sin_addr),ntohs(cli.sin_port));
        //5.收发数据(重点)
        char buf[64]={0};
        char str[64]={0};
        while(1)
        {
            int n=read(connfd,buf,64);
            if(n<0)
            {
                perror("read");
                return -1;
            }
            else if(n==0)//客户端关闭了
            {
                break;
            }

            if(strcmp(buf,"time")==0)//显示时间
            {
                time_t my_t;
                time(&my_t);
                struct tm *t=localtime(&my_t)  ;
                sprintf(str,"%02d年%02d月%02d日 %02d:%02d:%02d\n",t->tm_year+1900,t->tm_mon+1,t->tm_mday,t->tm_hour,t->tm_min,t->tm_sec);   
                send(connfd,str,64,0);
                memset(buf,0,64);//数组清空
                memset(str,0,64);
            }  

            else if(strncmp(buf,"get",3)==0)//显示文件内容
            {
                char name[64]={0};
                strcpy(name,buf+4);
                puts("name");
                int fd=open(name,O_RDWR);
                if(fd<0)
                {
                    perror("open");
                    return -1;
                }
                int n;
                while((n=read(fd,buf,64)))//读完退出
                {
                    printf("n=%d\n",n);
                    send(connfd,buf,n,0);
                    memset(buf,0,64);//数组清空
                }
                //send(connfd,"over",5,0);//对面接受完成的标志
                printf("send %s\n",name);
                close(fd);
            }
            else//正常情况,求字符串长度
            {
                printf("message:%s\n",buf);

                sprintf(str,"%ld",strlen(buf));
                send(connfd,str,64,0);
                memset(buf,0,64);//数组清空
                memset(str,0,64);
            }
        }
        close(connfd);
    }

    
    close(sockfd);
    return 0;
} 

客户端:

/*===============================================
*   文件名称:server.c
*   创 建 者:     
*   创建日期:2022年08月16日
*   描    述:
================================================*/
#include <stdio.h>
#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <unistd.h>
#include <string.h>
#include <time.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

int main(int argc, char *argv[])
{ 
    //1.创建监听套接字
    int sockfd = socket(AF_INET,SOCK_STREAM,0);
    if(sockfd <0)
    {
        perror("sockfd");
        return -1;
    }
    //2.接收连接
    struct sockaddr_in ser;
    ser.sin_family=AF_INET;
    ser.sin_port=htons(8888);
    //ser.sin_addr.s_addr=inet_addr("0.0.0.0");//"0"表示本机的所有ip
    ser.sin_addr.s_addr=htonl(INADDR_ANY);//"0"表示本机的所有ip
    
   int ret= connect(sockfd,(struct sockaddr *)&ser,sizeof(ser));//建立连接
    if(ret<0)
    {
        perror("connect");
        return -1;
    }

    char buf[64]={0};//储存数据
    char len[64]={0};//储存字符串长度
    while(1)
    {
        fgets(buf,64,stdin);		//终端输入
        buf[strlen(buf)-1]='\0';
        int n=send(sockfd,buf,64,0);
        if(n<0)
        {
            perror("read");
            return -1;
        }
        else if((strcmp(buf,"quit"))==0)//客户端请求关闭
        {
            break;
        }
        else if(strcmp(buf,"time")==0)//接收时间
        {
        	read(sockfd,len,64);
        	printf("time: %s\n",len);
        	memset(len,0,64);
        }
        else if(strncmp(buf,"get",3)==0)//接收文件内容
        {
        	
        	
        	int fd=open("2.txt",O_RDWR | O_CREAT |O_TRUNC ,0664);
        	if(fd<0)
        	{
        		perror("open");
        		return -1;
        	}
        	
        	int count=0;
        	while((count=recv(sockfd,buf,64,0)))
        	{
        	
        		//if(strcmp(buf,"over")==0)//服务器发送完毕后会发送over提示已发送完毕
        		
        		
        		printf("%s \n",buf);
        		write(fd,buf,strlen(buf));
        		//write(1,buf,64);
        		memset(buf,0,64);//数组清空
        		if(count<64)
        		{
        			close(fd);
        			memset(buf,0,64);
        			break;
        		}
        		
        	}
        	printf("recv -------------------------------\n");
        	close(fd);
        }
		else	//接收字符串长度
		{
        	read(sockfd,len,64);
        	printf("len=%s\n",len);
        	memset(len,0,64);
        	memset(buf,0,64);//数组清空
    	}
    }

    close(sockfd);
    return 0;
} 

运行结果:

 

  • 5
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值