linux--网络编程(8)

通信协议(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 4999

int 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 1024

void *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 1024

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;

    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 1024


void *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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值