Linux基础(05)socket编程

 Linux的核心思想之一 "一切皆文件" 

1.  例如本地文件对一个字符串的"aaaaaaa"的读写是 open()返回的句柄 fd 作为载体, 调用 write 和 read 进行读写

  而网络文件的和本地文件差不多但多了一些特性  用socket()返回的句柄 socket 传输读写数据前 要再创建一个sockaddr_in 对象 设置好协议族family 地址ip 端口prot 后 把设置好的sockaddr_in 对象利用 bind() 和 socket 绑定 ; 再用 listen()监听socket 有哪些连接和设置最大监听数量

    完成上述一系列后可以调用 write 和 read 进行读写 , 也有一些特殊的: accept()  connect()  (setsocketopt()设置sendbuff和recvbuff的size)

2.内核的socket就是这样一个简单的结构 , 里面每种结构都是函数指针或变量的集合 , 

      方便实现每种协议的接口函数名和最终目的相同,但是实现过程却不同的面向对象思想

在Linux内核里 ops是一些函数的集合如accept() connect()等 , file里是一些write() read() 等 , sk是 bind() listen() 等;

       每种协议栈的接口函数名是相同的但是内部实现是不同的

3.在创建cocket对象时要告诉内核你要使用哪种协议 , socket()第一个参数添加ipv4/ipv6协议 第三个参数添加TCP/UDP协议也可以为0(默认具体依赖第二个参数) , 第二个参数,如果是流套接字的SOCK_ STREAM默认是TCP协议的 , 如果是数据包套接字SOCK_DGRAM默认是UDP ,还有个原始套接字SOCK_RAW是使用其他协议,具体要给第三个参数

4.TCP/IP协议

  4.1分层概念 : mac  ip  tcp

    物理层 MAC(源MAC 目标MAC 长度和类型L/T )------>ARP 解决链路和物理连接问题

    网络层 IP  解决远程通信问题

    传输层 TCP/UDP ---->端口(对应了本机的某个进程) 决定了数据传给哪个进程

    应用层 HTTP HTTPS FTP TELNET SSH

  4.2 ip格式 点分十进制 二进制

      网络字节序(大端)0x12 0x34 0x56 x078 本地字节序(小端) 0x78 0x56 0x34 0x12

      case 1 : 点分十进制 转换 网络字节序的二进制  有个专用函数  in_addr_t inet_addr(const char* cp);

      case2 : 网络字节序的二进制 转换 点分十进制          char* inet_ntoa(struct in_addr_t in);

  4.3子网掩码 用于确定网段的范围  24位能用0~255个ip地址  28位能用14个IP地址和一个255广播地址

      24 == 32位二进制中有 24位是1 剩下的8位是0 (一个字节2位)

      255.255.255.0  == 11111111.11111111.11111111.00000000

  4.4 拆包和封包过程

5.TCP编程原理和流程

 

阻塞调用是指调用结果返回之前,当前线程会被挂起。函数只有在得到结果之后才会返回;  connect 和  accept 都是阻塞函数

  5.1 服务端 create socket 

int sock = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
if(sock < 0)
{
    perror("creat socket error\n");
    return 1;
}
//sockaddr_in 设置时用 sockaddr_in 调用时强转成sockaddr
struct sockaddr_in local;  //设置family port ip
local.sin_family = AF_INET;
//htons h: honst  n: network s:short 把本地端口转换成网络的 , atoi 把字符串转换成整型 ,ntohs和htons相反
local.sin_port = htons(atoi(argv[2]));   
local.sin_addr.s_addr = inet_addr(argv[1]); //inet_addr点分十进制转换网络二进制 

  bind()

if(bind(sock,(struct sockaddr*)&local,sizeof(local)) < 0)
{
    perror("bind error\n");
    close(sock);
    return 2;
}

  listen()

if(listen(sock,10) < 0){
        perror("listen error\n");
        close(sock);
        return 3;
    }

    printf("bind and listen success!wait accept...\n");

  accept   read write

struct sockaddr_in peer;  //保存客户端信息
socklen_t len = sizeof(peer);
while(1)
{   
int fd = accept(sock,(struct sockaddr*)&peer ,&len);  //阻塞函数   if(fd < 0){     perror("accept error\n");     close(sock);     return 4;   }   printf("get connect,ip is : %s port is : %d\n",inet_ntoa(peer.sin_addr),ntohs(peer.sin_port));   pthread_t id;   pthread_create(&id,NULL,thread_run,(void*)fd);   pthread_detach(id);
}
close(sock);
 
 

void thread_run(void *arg)
{
  printf("creat a new thread\n");
  int fd = (int)arg;
  char buf[1024];

  while(1){

    memset(buf,'\0',sizeof(buf));
    ssize_t _s = read(fd,buf,sizeof(buf) - 1);
    if(_s > 0){
      buf[_s] = '\0';
      printf("client say : %s\n",buf);
    }
    memset(buf,'\0',sizeof(buf));
    printf("please Enter: ");
    fflush(stdout);  //清空堆里的printf内容
    ssize_t _s2 = read(0,buf,sizeof(buf) - 1);
    if(_s2 > 0){
      write(fd,buf,strlen(buf));
    }
  }
}

   5.2 客户端 creater socket

int sock = socket(AF_INET,SOCK_STREAM,0);
    if(sock < 0){
        perror("socket error");
        return 1;
    }
struct sockaddr_in remote;
remote.sin_family = AF_INET;
remote.sin_port = htons(atoi(argv[2]));
remote.sin_addr.s_addr = inet_addr(argv[1]);

  connect

int ret = connect(sock,(struct sockaddr*)&remote,sizeof(remote));
    if(ret < 0){
        printf("connect failed:%s\n",strerror(errno));
        return 2;
    }
    
    printf("connect success!\n");

  read write

char buf[1024];
while(1){
  memset(buf,'\0',sizeof(buf));
  printf("please enter:");
  fflush(stdout);
  ssize_t _s = read(0,buf,sizeof(buf)-1);
  if(_s > 0){
    buf[_s - 1] = '\0';
    write(sock,buf,strlen(buf));
    _s = read(sock,buf,sizeof(buf)-1);
    if(_s > 0){
      if(strncasecmp(buf,"quit",4) == 0){
        printf("qiut\n");
        break;
      }
      buf[_s -1] = '\0';
      printf("%s\n",buf);
    }
  }
}
close(sock);    

猜你喜欢

转载自www.cnblogs.com/yxnrh/p/11494700.html
今日推荐