UnixC第十二天

回忆昨天内容
    一、system v ipc
    共享内存
    获取一个键值
    使用键值获取一个共享内存段的id
    将共享内存段关联到进程的虚拟地址(内存)
    不再使用这个共享内存段的时候,解除关联
    二、网络的基础
    TCP/IP协议簇
    四层或者五层
    应用层  传输层 网络层  链路层  物理层
    ip地址   mac地址
    有两部分构成  网络号  主机号
    子网掩码 
    ifconfig  ping   route    arp
    网帧的结构    ip报文   tcp包
    局域网内数据的传输
    跨网段数据的传输
    三、基于TCP的网络模型
    三次握手  四次分手
今天内容:
一、基于tcp的编程
    模型:
     服务器端:
        1 创建一个通讯设备,返回该设备的文件描述符
        2 将sfd绑定到服务器的地址和端口号
        3 将sfd设置为被动连接状态  等待客户端连接的到来,有连接到来,将连接放入未决连接队列中。
如果未决连接队列满,通知客户端。  
        while(1)
        {
            4 从未决队列中,取出一个连接 进行处理
                返回一个真正的和客户端的连接
                (处理,就是跟客户端的连接)
            5 从连接里读取客户端的消息read
            6 处理消息
            7 处理结果 ,响应给客户端write    
            8 关闭连接
        }

    客户端:
    1 创建一个socket设备,返回该设备的文件描述符(fd)
    2 在fd上向服务器发连接
    3 (连接成功)向服务器发送消息
    4 等待服务器的响应信息
    5 处理服务器的响应信息
    6关闭和服务器端的连接
实现:
socket(2)
     #include <sys/types.h>          /* See NOTES */
       #include <sys/socket.h>

       int socket(int domain, int type, int protocol);
    功能:创建一个通讯端点
    参数:
        domain
             AF_INET             IPv4 Internet protocols          ip(7)
                   AF_INET6            IPv6 Internet protocols          ipv6(7)

        type
             SOCK_STREAM 有序的   可靠的   基于连接的字节流  双向的  TCP
             SOCK_DGRAM  面向数据包的  不可靠 连接可有可无   UDP

        protocol 0
    返回值:成功  返回新的文件描述符、
        失败 -1  errno被设置
    

bind(2)
     #include <sys/types.h>          /* See NOTES */
       #include <sys/socket.h>

       int bind(int sockfd, const struct sockaddr *addr,socklen_t addrlen);

    功能:给socket设备绑定一个名字(name?    地址家族)
    参数:
        sockfd 指定socket设备
        addr 指定具体的地址
        addrlen  addr的空间的大小
    返回值:成功 0
        错误 -1   errno被设置

        struct sockaddr?
      struct sockaddr {//通用地址家族
               sa_family_t sa_family;
               char        sa_data[14];
               }
ipv4地址家族  ipv6地址家族
        

     #include <netinet/in.h>

     struct sockaddr_in {
               sa_family_t    sin_family; /* address family: AF_INET */
               in_port_t      sin_port;   /* port in network byte order */
               struct in_addr sin_addr;   /* internet address */
           };

           /* Internet address. */
           struct in_addr {
               uint32_t       s_addr;     /* address in network byte order */
           };
    ip地址和端口号
    in_port_t  无符号的短整型 2字节
    uin32_t    无符号的整型  4字节
    网络字节序 大端
    
    主机字节序<-->网络字节序
     #include <arpa/inet.h>

       uint32_t htonl(uint32_t hostlong);

       uint16_t htons(uint16_t hostshort);

       uint32_t ntohl(uint32_t netlong);

       uint16_t ntohs(uint16_t netshort);
    
    h   host
    n   net
    l   long
    s   short
    to  
    ip地址 192.168.1.24
    字符串   <-->  无符号整型
    text  <--> binary
       inet_pton(3)
     #include <arpa/inet.h>

 int inet_pton(int af, const char *src, void *dst);
    功能:将ipv4和ipv6地址从text转换为binary
    参数:   af  指定地址家族
            AF_INET  指定ipv4
            AF_INET6  指定ipv6
        src  ip地址字符串格式
        dst  存储转换后的结果  struct in_addr
    返回值:成功返回1
        地址家族不存在 -1   errno被设置
        0   ip地址不合法
    binary-->text
        inet_ntop(3)
     #include <arpa/inet.h>

       const char *inet_ntop(int af, const void *src,char *dst, socklen_t size);

    功能:
、    参数:
        af  指定地址家族
        src 地址的结构体      struct in_addr
        dst  指定了存储空间  转换后的字符串存放到dst指向的空间里
        size  指定了dst有效空间的大小
    返回值:成功返回指向dst的非空指针
        失败返回 null   errno被设置
             
        man 7 ip
    
        
listen(2)
       #include <sys/types.h>          /* See NOTES */
       #include <sys/socket.h>

       int listen(int sockfd, int backlog);
    功能: 监听客户端连接的到来  将其放入未决连接队列
    参数:
    sockfd 指定了一个socket 将这个socket设置为被动模式
    backlog 指定了未决连接队列的最大数
    返回值:成功  返回0
        错误 -1  errno被设置
        

accept(2)
      #include <sys/types.h>          /* See NOTES */
       #include <sys/socket.h>

       int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
    功能:受理一个连接
    参数:
    sockfd 指定socket  这是监听客户端连接的socket  从这个socket的未决连接队列里取出第一个未决连接请求,
进行处理。返回一个连接描述符
    addr 将客户端的地址存储到addr指向的地址空间里。
    addrlen addr结构体的尺寸
    返回值: 错误-1  errno被设置
        成功  返回一个新的描述符 和客户端的连接
    举例说明  编写基于tcp的服务器端
    代码参见  server.c
connect(2)
      #include <sys/types.h>          /* See NOTES */
       #include <sys/socket.h>

       int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
    功能:在socket上发起一个连接
    参数:sockfd   指定socket 在这个socket向addr发起连接
        addr  指定了地址空间,向这个地址空间发起连接
        addrlen   addr的尺寸
    返回值:成功返回0
        错误 -1  errno被设置


将字符串从小写转换为大写    toupper(3)  #include<ctype.h>
    
    
    

        

 

server.c

#include<t_stdio.h>
#include<t_file.h>
#include<sys/socket.h>
 #include<ctype.h>
#include<netinet/in.h>
#include<arpa/inet.h>
int main(){
//	  struct sockaddr serv;//通用地址
		struct sockaddr_in serv,clie;//具体ipv4地址
	  char* buf;
	  int r;
	  socklen_t len;
	  char ip[32];
	//创建socket 返回该设备的文件描述符	
	int sfd=socket(AF_INET,SOCK_STREAM,0);
	if(sfd==-1) E_MSG("socket",-1);
	//初始化服务器的ip地址和端口
	serv.sin_family=AF_INET;
	serv.sin_port=htons(3333);
	serv.sin_addr.s_addr=htonl(INADDR_ANY);//本地所有端口的ip地址

	//将sfd绑定到本地地址
	int b=bind(sfd,(struct sockaddr*)&serv,sizeof(serv));
	if(b==-1) E_MSG("bind",-1);

	//将sfd设置为被动连接  监听客户端的连接					
	//连接到来的时候,将连接放入未决连接队列中
	int l=listen(sfd,5);
	if(l==-1) E_MSG("listen",-1);
	while(1){//受理连接
		len=sizeof(clie);
		int cfd=accept(sfd,(struct sockaddr *)&clie,&len);
		if(cfd==-1) E_MSG("accept",-1);
		//客户端ip地址和端口保存到clie结构体中了
		//binary-->text
		printf("%s\n",inet_ntop(AF_INET,&clie.sin_addr,ip,32));
		//从连接描述符中读取客户端发送来的数据到buf中
		
		r=read(cfd,buf,128);
		//处理客户端的数据
		for(int i=0;i<r;i++)
			buf[i]=toupper(buf[i]);
	//	buf="Stupid JerryFeng\n";
		//响应客户端
		write(cfd,buf,r);
		//关闭
		
		close(cfd);
	}

	return 0;
}

client.c

#include<t_stdio.h>
#include<t_file.h>
#include<t_neth>
#include<string.h>


int main(int argc,char* argv[]){
	  struct SA serv;
	  char *msg="this is a test...\n";
	  char buf[128];
	//创建socket  返回该设备的文件描述符
	int sfd=socket(AF_INET,SOCK_STREAM,0);
	if(sfd==-1) E_MSG("socket",-1);
	//初始化服务器的ip地址和端口号
	serv.sin_family=AF_INET;
	serv.sin_port=htons(3333);
	//知道服务器的ip地址 127.0.0.1
	inet_pton(AF_INET,argv[1],&serv.sin_addr);
	//向服务器发起连接
	int c=connect(sfd,(SA *)&serv,sizeof(serv));//触发三次握手
	if(c==-1) E_MSG("connect",-1);
	//如果连接服务器成功
	//向服务器发送消息
	while(1){
	//	scanf("%s",buf);
	write(sfd,msg,strlen(msg));//没有字符串最后的'\0'
	//等待服务器的响应消息
	int r=read(sfd,buf,128);
	write(1,buf,r);
	}
	//关闭本次连接
	close(sfd);
	return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值