Unix C (十)

来源:互联网 发布:必备的办公软件 编辑:程序博客网 时间:2024/06/05 10:41
网络编程:
  ip 地址 是网络中计算机的地址,和mac地址(网卡出厂地址/物理地址)联合 能够让网络找到计算机。用端口(port)定位一个进程。因此网络编程就是 ip+端口。
  Unix系统中,几乎一切都可以看成文件。因此网络信息的交互就用文件的交互方式。
  ip地址底层是整数,分为ipv4(4位ip)和ipv6(6位)。
  对ip的描述方式一般使用点分十进制。4个或者6个 0-255的数字,并用 . 分开。底层ipv4其实就是一个32位二进制。

 在网络中,字节顺序固定,但本机中,可能从低到高,也可能从高到低。


 端口:16位二进制(0-65535)
  0-1023 尽量不用,系统会非连续的使用
  1024-48XXX  使用,固有端口
  48XXX-65535 不要使用,动态端口(不稳定)


 编程:
  1 socket套接字
    socket 编程  分类:
     一对一(点对点)
     一对多(多个客户端/一个服务器)
    支持TCP/UDP传输


   1.1 一对一本地通信
    a 服务端 
     1) 创建一个socket
  int socket(int domain,int type,int protocol)
   domain: 域 ,选择协议簇
     PF_UNIX / PF_LOCAL / PF_FILE (PF换AF)
      本地通信(进程间通信)
     PF_INET/AF_INET 网络通信(IPV4) 
     PF_INET6/AF_INET6 网络通信(IPV6)   
   type : 通信协议的类型
    SOCK_STREAM : 数据流(TCP)
    SOCK_DGRAM  :数据报(UDP)
   protocol : 本来应该是选协议,但基本没用,因为协议由前2个参数决定


   返回值是一个整数,socket描述符。socket描述符类似文件描述符,read读,write写。
    2) 准备通信地址
     参数通信地址(只是做参数,不会真正使用)
      struct sockaddr{
        int sa_family;//协议簇
        char sa_data[];//地址
      };
     本地通信地址(文件):
     struct sockaddr_un{ // sys/un.h
       int sun_family;//协议簇
       char sun_path[];//文件名

     };

实例:

(1)

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <string.h>


int main(){
//创建通信描述符
  int sockfd = socket(PF_UNIX,SOCK_DGRAM,0);
  if(sockfd == -1)
perror("socket"),exit(-1);


//准备本地通新地址
  struct sockaddr_un addr;
  addr.sun_family = PF_UNIX;
  strcpy(addr.sun_path,"a.sock");


  //连接
  int res = connect(sockfd,(struct sockaddr*)&addr,sizeof(addr));
  if(res == -1)
perror("bind"),exit(-1);
  printf("connect ok\n");


  //写内容
  write(sockfd,"hello socket!",13);
  printf("成功写出\n");


  //关闭描述符
  close(sockfd);


  return 0;
}

(2)

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <string.h>


int main(){
//创建通信描述符
  int sockfd = socket(PF_UNIX,SOCK_DGRAM,0);
  if(sockfd == -1)
perror("socket"),exit(-1);


//准备本地通信地址
  struct sockaddr_un addr;
  addr.sun_family = PF_UNIX;
  strcpy(addr.sun_path,"a.sock");


  //绑定
  int res = bind(sockfd,(struct sockaddr*)&addr,sizeof(addr));
  if(res == -1)
perror("bind"),exit(-1);
  printf("bind ok\n");


  //读取内容
  char buf[100] = {};
  read(sockfd,buf,sizeof(buf));
  printf("读到了:%s\n",buf);


  //关闭描述符
  close(sockfd);


  return 0;
}

     网络通信地址(ip和端口):
    struct sockaddr_in{ // netinet/in.h
       int sin_family;//协议簇
       short sin_port;//端口
       struct in_addr sin_addr;//IP

     };

   

网络编程:
  基于TCP的编程步骤:
  Server端:
   1 socket()
   2 准备通信地址  struct sockaddr_in
   3 绑定 bind()
   4 listen()
   5 accept(),返回一个用于交互的新的描述符
   6 读写 read() write()
   7 关闭close()
  Client端:
   1 socket()
   2 准备通信地址  struct sockaddr_in
   3 连接 connect()
   4 读写 read() write()
   5 关闭close()
  基于UDP的编程步骤:
   接收方:
   1 socket()
   2 准备通信地址,struct sockaddr_in
   3 绑定 bind()
   4 发送或接收 sendto()  recvfrom() read()
   5 关闭close()
   发送方:
   1 socket()
   2 准备通信地址,struct sockaddr_in
   3 发送或接收 sendto()  recvfrom() read()
   4 关闭close()

实例:

TCP通信

(1)服务端

#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <signal.h>
#include <string.h>
//实现一对多
void fa(int signo){
  printf("服务器即将退出\n");
  //sleep(1);
  exit(0);
}


int main(){
  signal(SIGINT,fa);
  //1 创建socket,accept不支持UDP
  int sockfd = socket(PF_INET,SOCK_STREAM,0);
  if(sockfd == -1) perror("socket"),exit(-1);
  //2 准备通信地址
  struct sockaddr_in addr;
  addr.sin_family = PF_INET;
  addr.sin_port = htons(2222);
  addr.sin_addr.s_addr = inet_addr("172.40.0.65");

  //addr.sin_addr.s_addr = INADDR_ANY;//本机ip


  //防止地址已经使用
  int reuseaddr = 1;
  setsockopt(sockfd,SOL_SOCKET,SO_REUSEADDR,&reuseaddr,sizeof(reuseaddr));


  //3 绑定
  int res = bind(sockfd,(struct sockaddr*)&addr,sizeof(addr));
  if(res == -1) perror("bind"),exit(-1);
  printf("bind ok\n");
  
  //4 监听
  if(listen(sockfd,100)==-1)perror("list"),exit(-1);
  printf("listen........\n");
  
  //5 等待客户端的连接
  while(1){
    struct sockaddr_in clientaddr;
    socklen_t len = sizeof(clientaddr);
    int fd = accept(sockfd,//阻塞,直到客户端连接
 (struct sockaddr*)&clientaddr,&len);
    if(fd == -1) perror("accept"),exit(-1);
    char *ip = inet_ntoa(clientaddr.sin_addr);//转换
    printf("客户端%s连接了服务器\n",ip);
pid_t pid = fork();
if(pid == 0){
    //6 用fd进行信息交互
      while(1){
   char buf[100] = { };
        if(read(fd,buf,100)==-1)
perror("read"),exit(-1);
        printf("读到了:%s\n",buf);
        write(fd,buf,strlen(buf));
   }
      close(fd);//练习:用信号在关闭服务器时打印信息
 exit(0); 
}
  }
  //close(sockfd);//7 关闭
}

(2)客户端:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>


int main(){
//创建网络通信描述符
  int sockfd = socket(PF_INET,SOCK_STREAM,0);
  if(sockfd == -1)
perror("socket"),exit(-1);


//准备通信地址
  struct sockaddr_in addr;
  addr.sin_family = PF_INET;
  addr.sin_port = htons(2222);
  addr.sin_addr.s_addr = inet_addr("172.40.0.65");

  //addr.sin_addr.s_addr = INADDR_ANY;//本机ip


  //连接服务器
  int res = connect(sockfd,(struct sockaddr*)&addr,
 sizeof(addr));
  if(res == -1) perror("connect"),exit(-1);


  //通信
  while(1){
char bufscan[100] = {};
printf("请输入要说的话\n");
scanf("%s",bufscan);
    res = write(sockfd,bufscan,strlen(bufscan));
    if(res == -1)
perror("write"),exit(-1);
if(strcmp(bufscan,"bye")==0) break;
    char buf[100] = {};
    res = read(sockfd,buf,100);
    if(res == -1)
perror("read"),exit(-1);
    printf("读到了:%s\n",buf);
  }  
  close(sockfd);
}


UDP通信

(1)服务端

#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <unistd.h>
#include <arpa/inet.h>


int main(){
//创建网络通信描述符
  int fd = socket(AF_INET,SOCK_DGRAM,0);   
  if(fd==-1) 
  perror("socket"),exit(-1);
 
 //准备通信地址
  struct sockaddr_in addr;
  addr.sin_family = AF_INET;
  addr.sin_port = htons(2222);
  addr.sin_addr.s_addr = inet_addr("172.40.0.11");
  
  //绑定
  int res = bind(fd,(struct sockaddr*)&addr,sizeof(addr));
  if(res==-1)
  perror("bind"),exit(-1);
  printf("bind ok\n");
  
  //通信
  char buf[100] = {};
  struct sockaddr_in from;
  socklen_t length = sizeof(from);
  int len = recvfrom(fd,buf,sizeof(buf),0,(struct sockaddr*)&from,&length);
  printf("读到%d字节,内容:%s\n",len,buf);
  sendto(fd,"welcome",7,0,(struct sockaddr*)&from,length);
  
  //关闭描述符
  close(fd);
  
  return 0;
}

(2)客户端

#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <unistd.h>
#include <arpa/inet.h>


int main(){
//创建通信描述符
  int fd = socket(AF_INET,SOCK_DGRAM,0);   
  if(fd==-1) 
  perror("socket"),exit(-1);
 
 //准备通信地址
  struct sockaddr_in addr;
  addr.sin_family = AF_INET;
  addr.sin_port = htons(2222);//服务端口
  addr.sin_addr.s_addr =inet_addr("172.40.0.11");
  //UDP无连接协议,理应不connect就能发送
  //int res = write(fd,"hello",5);
  
  //通信
  int res = sendto(fd,"hello",5,0,(struct sockaddr*)&addr,sizeof(addr));
  if(res==-1) 
  perror("write"),exit(-1);
  char buf[100] = {};
  read(fd,buf,sizeof(buf));
  printf("buf=%s\n",buf);
  
  close(fd);
  
  return 0;
}


0 0
原创粉丝点击