linux--网络编程(8)

来源:互联网 发布:制造业软件 编辑:程序博客网 时间:2024/06/06 15:47

通信协议(OSI、TCP/IP)

  • OSI协议(七层网络协议)
    下三层
    1物理层(类似网卡(接收传输数据))
    2链路层(解析数据)
    3网络层(选择数据传送)
    高四层
    4传输层(提供端对端接口(传输数据))
    5会话层(会话x,(解除或建立联系))
    6表示层(表示x,(加密、转换))
    7应用层(行动x(展示网络服务))

  • TCP/IP协议(四层协议)
    这里写图片描述

    • TCP/IP 具有两个主要功能。第一是IP 在网络之间(有时在个别网络内部)提供路由选择。第二是TCP 将TP 传递的数据传送的接收主机那的适当的处理部件。
    • 套接字(类似SIM卡)
      套接字有三种类型:流式套接字(SOCK_STREAM),数据报套接字(SOCK_DGRAM)及原始套接字
    • 流式套接字
      流式的套接字可以提供可靠的、面向连接的通讯流。如果你通过流式套接字发送了顺序的数据:“1”、“2”。那么数据到达远程时候的顺序也是“1”、“2”。采用TCP协议
      这里写图片描述
      数据报套接字
      一种无连接的服务,数据通过相互独立的报文进行传输,是无序的,并且不保证可靠,无差错,使用者数据报协议UDP(User Datagram Protocol )
      这里写图片描述
      原始套接字
      主要用于一些协议的开发,可以进行比较底层的操作

TCP协议:
三次握手:请求连接–>授权—>连接
这里写图片描述
四次关闭:客户端请求关闭—>服务端可以关了—>客户端关了—>服务端也关了
这里写图片描述


socket基本函数

htons() 主机字节顺序转换为网络字节顺序(对无符号短型进行操作4 bytes)
htonl() 主机字节顺序转换为网络字节顺序(对无符号长型进行操作8 bytes)
ntohs() 网络字节顺序转换为主机字节顺序(对无符号短型进行操作4 bytes)
ntohl() 网络字节顺序转换为主机字节顺序(对无符号长型进行操作8 bytes)
close() 关闭套接字,任何有关对套接字描述符进行读和写的操作都会接收到一个错误。
shutdown() 允许你进行单向的关闭操作,或是全部禁止掉(0不接 1不发 2全关)
setsockopt() 、 getsockopt() 设置和获取套接字的属性
getpeername() 获取连接上的远程信息

socket(TCP/IP)代码

    1. IP和主机地址处理
/******** IP和主机地址 *************/#include <stdio.h>#include <stdlib.h>#include <netdb.h>#include <netinet/in.h>/*struct sockaddr_in{                      //“in” 代表 “Internet”    short int sin_family;              // Internet地址族    unsigned short int sin_port; // 端口号     struct in_addr sin_addr;      // Internet地址    unsigned char sin_zero[8]; // 添0(和struct sockaddr一样大小)};*/int main(int argc, char *argv[]){    struct hostent *host;    //域名解析成IP    host = gethostbyname(argv[1]);    //字符串转成整型inet_addr()    printf("%d\n", inet_addr("166.111.69.52"));    printf("hostname == %s\n", host->h_name);    //整机转成字符串inet_ntoa()    printf("ip == %s\n", inet_ntoa(((struct in_addr *)(host->h_addr_list[0]))->s_addr));    return 0;}
  • 2.socket函数
//1.网络协议一般是AF_INET  2.TCP(SOCK_STREAM)或者UDP(SOCK_STREAM)3.一般为0//int socketint family , int type , int protocol);   ------买电话机//1.电话机2.绑定端口号码 3.//int bind (int sockfd , struct sockaddr *my_addr , int addrlen) ;--------插线(2绑定到1上)//1.电话机 2.同时监听的个数(一般5--10)//int listen(int sockfd, int backlog); --------待机(监听)//1.电话机 2.传过来的地址 3.//int accept(int sockfd, void *addr, int *addrlen) ----------接听
  • 3.基本socket的建立
/***********基本步骤(服务端.c)***********/#include <stdio.h>#include <stdlib.h>#include <errno.h>#include <string.h>#include <sys/types.h>#include <netinet/in.h>#include <sys/socket.h>#include <sys/wait.h>#define PORT 4999int main(int argc, char *argv[]){    int sfd;    int accept_fd;    struct sockaddr_in addr;    struct sockaddr_in client_addr;    char buf[128];    int size;    int ret;    //创建socket    sfd = socket(AF_INET, SOCK_STREAM, 0);    memset(&addr, 0, sizeof(struct sockaddr_in));    //绑定端口    printf("===create socket===\n");    addr.sin_family = AF_INET;    addr.sin_port = htons(PORT);    addr.sin_addr.s_addr = INADDR_ANY;    printf("===bind===\n");    bind(sfd, (struct sockaddr *)&addr, sizeof(struct sockaddr_in));    //监听    printf("===listen===\n");    listen(sfd, 10);    //接收    printf("===accept===\n");    size = sizeof(struct sockaddr);    accept_fd = accept(sfd, (struct sockaddr *)&client_addr, &size);    printf("===send===\n");    //读取或输出    memset(buf, 0, sizeof(buf));    strcpy(buf, "abc");    ret = send(accept_fd, buf,strlen(buf),0);    printf("==ret is:%d\n", ret);    sleep(10);    close(accept_fd);    close(sfd);    return 0;    return 0;}----------------------------------------------/***********基本步骤(客户端.c)***********/#include <stdio.h>#include <stdlib.h>#include <errno.h>#include <string.h>#include <sys/types.h>#include <netinet/in.h>#include <sys/socket.h>#include <sys/wait.h>int main(int argc, char *argv[]){    int sfd;    int accept_fd;    struct sockaddr_in addr;    struct sockaddr_in client_addr;    char buf[128];    int ret;    sfd = socket(AF_INET, SOCK_STREAM, 0);    memset(&addr, 0, sizeof(struct sockaddr_in));    memset(&addr, 0, sizeof(struct sockaddr_in));    addr.sin_family = AF_INET;    addr.sin_port = htons(4999);    addr.sin_addr.s_addr = inet_addr("127.0.0.1");    ret = connect(sfd, (struct sockaddr *)&addr, sizeof(struct sockaddr_in));    memset(buf, 0, 128);    ret = recv(sfd, buf, 128, 0);    printf("===buf===:%s\n", buf);    close(sfd);    return 0;}
  • 3.复杂点的socket
/************实现多个客户端对一个客户端(服务端.C)*************/#include<stdio.h>#include<stdlib.h>#include<errno.h>#include<string.h>#include<netdb.h>#include<unistd.h>#include<sys/types.h>#include<sys/socket.h>#include<sys/time.h>#include<sys/un.h>#include<sys/ioctl.h>#include<sys/wait.h>#include<netinet/in.h>#include<arpa/inet.h>#define SERVPORT 1234#define BACKLOG 20#define MAX_CON_NO 10#define MAX_DATA_SIZE 1024void *deal_msg(void *arg){    int newfd;    char sendBuf[MAX_DATA_SIZE], recvBuf[MAX_DATA_SIZE];    int recvBytes, sendBytes;    pthread_detach(pthread_self());    newfd = *(int *)arg;    while(1) {        /*  接收*/        if((recvBytes = recv(newfd, recvBuf,            MAX_DATA_SIZE, 0)) == -1){                perror("fail to receive datas");                exit(1);        }        printf("client :%s\n", recvBuf);        memset(recvBuf, 0x00, MAX_DATA_SIZE);        /*  发送*/        printf("server:");        gets(sendBuf);        if((sendBytes = send(newfd, sendBuf,            strlen(sendBuf), 0)) != strlen(sendBuf)){            perror("fail to receive datas");            exit(1);        }        printf("(success to send data!)\n");        memset(sendBuf, 0x00, MAX_DATA_SIZE);    }    close(newfd);    return NULL;}int main(int argc, char *argv[]) {    struct sockaddr_in serverSockaddr, clientSockaddr;    int sinSize, recvBytes, sendBytes;    pthread_t tid;    int sockfd, clientfd;    //char mac[6];    if(argc != 1) {        printf("usage:./server\n");        exit(1);    }    /*establish a socket*/    if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {        perror("fail to establish a socket");        exit(1);    }    printf("Success to establish a socket...(sockfd = %d)\n", sockfd);    /*init sockaddr_in*/    serverSockaddr.sin_family = AF_INET;    serverSockaddr.sin_port = htons(SERVPORT);    serverSockaddr.sin_addr.s_addr = htonl(INADDR_ANY);    bzero(&(serverSockaddr.sin_zero), 8);    int on = 1;    /*设置和套接字的属性*/    setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));    /*bind socket*/    if(bind(sockfd, (struct sockaddr *)&serverSockaddr,        sizeof(struct sockaddr))== -1) {        perror("fail to bind");        exit(1);    }    printf("Success to bind the socket...\n");    /*listen on the socket*/    if(listen(sockfd, BACKLOG) == -1) {        perror("fail to listen");        exit(1);    }    printf("Success to listen on the socket...\n");    while(1) {        sinSize = sizeof(struct sockaddr_in);        /*accept a client's request*/         if ((clientfd = accept(sockfd,             (struct sockaddr *)&clientSockaddr, &sinSize)) == -1) {            perror("fail to accept");            exit(1);            }        printf("success to accept=======\n");        /*改变打印颜色*/        printf("\033[40;32mWelcome to join %s!\033[1m\n",                   inet_ntoa(clientSockaddr.sin_addr));        /* 创建线程实现信号传递 */        pthread_create(&tid, NULL, deal_msg, &clientfd);   }}-----------------------------------------------------------/************实现多个客户端对一个客户端(客户端.C)*************/#include<stdio.h>#include<stdlib.h>#include<errno.h>#include<string.h>#include<netdb.h>#include<sys/types.h>#include<sys/socket.h>#include<netinet/in.h>#include<arpa/inet.h>#define SERVPORT 1234#define MAX_DATA_SIZE 1024int main(int argc, char *argv[]){    int sockfd, sendBytes,recvBytes;    char sendBuf[MAX_DATA_SIZE],recvBuf[MAX_DATA_SIZE];    struct hostent *host;    struct sockaddr_in servAddr;    if(argc != 2) {        fprintf(stderr,"usage:./client [hostname]");        exit(1);    }    /*translate the address*/    if((host = gethostbyname(argv[1])) == NULL) {        perror("fail to get host by name");        exit(1);    }    printf("Success to get host by name...\n");    /*establish a socket*/    if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {        perror("fail to establish a socket");        exit(1);    }    printf("Success to establish a socket...\n");    /*init sockaddr_in*/    servAddr.sin_family = AF_INET;    servAddr.sin_port = htons(SERVPORT);    servAddr.sin_addr = *((struct in_addr *)host -> h_addr);    bzero(&(servAddr.sin_zero), 8);    /*connect the socket*/    if(connect(sockfd, (struct sockaddr *)&servAddr,        sizeof(struct sockaddr_in)) == -1) {        perror("fail to connect the socket");        goto _exit;    }    printf("Success to connect the socket...\n");    printf("\033[40;32mWelcome to join %s!\033[1m\n",                  inet_ntoa(servAddr.sin_addr));    //include color set    while(1) {        /*send datas to server*/        printf("Client:");        gets(sendBuf);        if ((sendBytes = send(sockfd, sendBuf, strlen(sendBuf),0))                        != strlen(sendBuf)){            perror("fail to send data!\n");            goto _exit;        }        printf("(success to send data!)\n");        memset(sendBuf, 0x00, MAX_DATA_SIZE);        /*recive datas to server*/        if ((recvBytes = recv(sockfd, recvBuf, MAX_DATA_SIZE, 0)) == -1){            perror("fail to send data!\n");            goto _exit;        }        printf("server :%s\n", recvBuf);        memset(recvBuf, 0, MAX_DATA_SIZE);    }_exit:    close(sockfd);}
  • 4.无限大小的数据传输socket
/*********服务端.c***************/#include<stdio.h>#include<stdlib.h>#include<errno.h>#include<string.h>#include<netdb.h>#include<unistd.h>#include<sys/types.h>#include<sys/socket.h>#include<sys/time.h>#include<sys/un.h>#include<sys/ioctl.h>#include<sys/wait.h>#include<netinet/in.h>#include<arpa/inet.h>#include "comm.h"#include "lst.h"#define SERVPORT 1234#define BACKLOG 20#define MAX_CON_NO 10#define MAX_DATA_SIZE 1024void *deal_msg(void *arg){    int newfd;    char http_buf[1500];    char sendBuf[MAX_DATA_SIZE], recvBuf[MAX_DATA_SIZE];    int recvBytes, sendBytes;    msg_head_t *msg;    char *msgbuf;    char buf[64];    int ret;    pthread_detach(pthread_srlf());    newfd = *(int *)arg;    while(1) {        memset(buf, 0, 64);        memset(&msg, 0 sizeof(msg_head_t));        ret = recv(newfd, &msg, sizeof(msg_head_t), 0);        msg = (msg_head_t *)buf;        recvBytes = msg.len;        printf("======recvBytes is :%d,%d\n", msg->len, ret);        msgbuf = malloc(recvBytes);        memset(msgbuf, 0, recvBytes);        recv(newfd, msgbuf, recvBytes, 0);        printf("==recv msgbuf:%s\n", msgbuf);        free(msgbuf);        break;        }    close(newfd);    return NULL;}int main(int argc, char *argv[]) {    struct sockaddr_in serverSockaddr, clientSockaddr;    int sinSize, recvBytes, sendBytes;    pthread_t tid;    int sockfd, clientfd;    int fdmax;    int ret;    int i = 0;    char mac[6];    fd_set readfs;    sock_array_t *pos, *pon;      if(argc != 1) {        printf("usage:./server\n");        exit(1);    }    /*establish a socket*/    if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {        perror("fail to establish a socket");        exit(1);    }    printf("Success to establish a socket...(sockfd = %d)\n", sockfd);    /*init sockaddr_in*/    serverSockaddr.sin_family = AF_INET;    serverSockaddr.sin_port = htons(SERVPORT);    serverSockaddr.sin_addr.s_addr = htonl(INADDR_ANY);    bzero(&(serverSockaddr.sin_zero), 8);    int on = 1;    /*设置和套接字的属性*/    setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));    /*bind socket*/    if(bind(sockfd, (struct sockaddr *)&serverSockaddr,        sizeof(struct sockaddr))== -1) {        perror("fail to bind");        exit(1);    }    printf("Success to bind the socket...\n");    /*listen on the socket*/    if(listen(sockfd, BACKLOG) == -1) {        perror("fail to listen");        exit(1);    }    printf("Success to listen on the socket...\n");    while(1) {        sinSize = sizeof(struct sockaddr_in);        /*accept a client's request*/         if ((clientfd = accept(sockfd,             (struct sockaddr *)&clientSockaddr, &sinSize)) == -1) {            perror("fail to accept");            exit(1);            }        printf("success to accept=======\n");        /*改变打印颜色*/        printf("\033[40;32mWelcome to join %s!\033[1m\n",                   inet_ntoa(clientSockaddr.sin_addr));        /* 创建线程实现信号传递 */        pthread_create(&tid, NULL, deal_msg, &clientfd);   }   return 0;}/*********客户端.c***************/#include<stdio.h>#include<stdlib.h>#include<errno.h>#include<string.h>#include<netdb.h>#include<sys/types.h>#include<sys/socket.h>#include<netinet/in.h>#include<arpa/inet.h>#include "comm.h"#define SERVPORT 1234#define MAX_DATA_SIZE 3096 int main(int argc, char *argv[]){    int sockfd, sendBytes,recvBytes;    char sendBuf[MAX_DATA_SIZE],recvBuf[MAX_DATA_SIZE];    struct hostent *host;    struct sockaddr_in servAddr;    msg_head_t *msg;    // int ret;    if(argc != 2) {        fprintf(stderr,"usage:./client [hostname]");        exit(1);    }    /*translate the address*/    if((host = gethostbyname(argv[1])) == NULL) {        perror("fail to get host by name");        exit(1);    }    printf("Success to get host by name...\n");    /*establish a socket*/    if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {        perror("fail to establish a socket");        exit(1);    }    printf("Success to establish a socket...\n");    /*init sockaddr_in*/    servAddr.sin_family = AF_INET;    servAddr.sin_port = htons(SERVPORT);    servAddr.sin_addr = *((struct in_addr *)host -> h_addr);    bzero(&(servAddr.sin_zero), 8);    /*connect the socket*/    if(connect(sockfd, (struct sockaddr *)&servAddr,        sizeof(struct sockaddr_in)) == -1) {        perror("fail to connect the socket");        goto _exit;    }    printf("Success to connect the socket...\n");    printf("\033[40;32mWelcome to join %s!\033[1m\n",                  inet_ntoa(servAddr.sin_addr));    //include color set    while(1) {        /*send datas to server*/        printf("Client:");        gets(sendBuf);        sendBytes = strlen(sendBuf);        msg = (msg_head_t *)malloc(sizeof(msg_head_t) + sendBytes + 1);        memset(msg, 0, sizeof(msg_head_t) + sendBytes + 1);        msg->len = sendBytes;        printf("===msg_len [%d]\n", msg->len);        strncpy(msg->data, sendBuf, strlen(sendBuf));        printf("==data is: %s\n", msg->data);        send(sockfd, msg, sizeof(msg_head_t) + msg->len + 1, 0);    }_exit:    close(sockfd);}/***************结构体头文件.h**********/#ifndef _COMM_H_#define _COMM_H_typedef struct msg_head_s{    int type;    int len;    char data[0];}msg_head_t;#endif

I/O多路复用

  • 作用:它能同时等待多个文件描述符,而这些文件描述符(套接字描述符)其中的任意一个进入读就绪状态。处理多个套接字使用
  • 基本函数
    Select()函数可以帮助你同时监视许多套接字。它会告诉你哪一个套接字已经可以读取数据,哪个套接字已经可以写入数据,甚至你可以知道哪个套接字出现了错误
  • 相关宏
    FD_ZERO(fd_set *set)将一个文件描述符集合清零
    FD_SET(int fd, fd_set *set)将文件描述符fd 加入集合set 中。
    FD_CLR(int fd, fd_set *set)将文件描述符fd 从集合set 中删除.
    FD_ISSET(int fd, fd_set *set)测试文件描述符fd 是否存在于文件描述符set 中.
0 0
原创粉丝点击