网络编程的基础--tcp/ip协议

1.tcp/ip 协议  

        上层为应用层,下层为底层

2.tcp通信

      服务器:

          (1)建立套接字 socket(int domain, int type, int protocol);           

            第一个参数:指定域,协议族
                            AF_UNIX, AF_LOCAL   Local communication              unix(7)    建立UNIX的协议
                            AF_INET             IPv4 Internet protocols          ip(7)    这个代表使用IPV4的协议族  ----> 32bit
                            AF_INET6            IPv6 Internet protocols          ipv6(7)    这个代表使用IPV6的协议族  ----> 128bit

            第二个参数:指定我们创建的套接字的类型
                      SOCK_STREAM    提供一种有序的、可靠、双向的,基于连接的字节流类型的一种套接字。  ----> TCP
                     SOCK_DGRAM     提供一种数据报的通讯方式,这种方式是无连接的,不可靠的,有固定最大数据通讯长度的这一种套接字  ----> UDP
            
            第三个参数:指定该套接字用这个协议族里面的哪个子协议。一般都用0。
            返回值:如果成功这个新建的套接字的fd,就会返回。如果出错就会返回-1。
 

          (2)绑定: bind(int sockfd, const struct sockaddr *addr,socklen_t addrlen);

                       第一个参数:就是前面返回的文件描述符。
                       第二个参数:指定我们通讯的地址,这个是一个通用的结构体,它的地址,由指定的协议族去决定的。
                       第三个参数:指定的是第二个参数地址的大小。

                       通用的结构体:
                           struct sockaddr {
                                   sa_family_t sa_family;        //指定所用的协议族。
                                   char        sa_data[14];    //这里是具体的地址填充的空间。
                           }
                         在头文件里面:#include <netinet/in.h>
                                 typedef uint32_t in_addr_t;    //表示其IP地址
                                 struct in_addr  
                                 {
                                     in_addr_t s_addr;    //这个IP地址,实际上是一个32位无符号的数据
                                 };

        描述我们网络socket地址     /* Structure describing an Internet socket address.  */
            
            typedef uint16_t in_port_t; //16位的端口号
            struct sockaddr_in
              {
                __SOCKADDR_COMMON (sin_);  //协议族
                in_port_t sin_port;        //端口号 2字节
                struct in_addr sin_addr;   //IP地址 4字节
                unsigned char sin_zero[8]; //填充8个字节,使其和其他的协议族的地址结构体大小一致。
              };

        端口号:
            小端的保存方式,低地址保存低位的数据。
            大端的保存方式,低地址保存高位的数据。
            
            #include <arpa/inet.h>
                h-->host(主机)
                n-->network(网络)
                l-->代表是32位
                s-->代表是16位
                htonl();
                htons();
                ntohl();
                ntohs();

          (3)监听 listen(int sockfd, int backlog);

                    第一个参数:前面新建的fd。
                    第二个参数:监听队列上最大的请求数。

          (4)接受链接    accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);

                     第一个参数:前面新建的fd。
                     第二个参数:用来保存客户端的地址信息。
                     第三个参数:用来保存客户端地址的长度。
            
                     返回值:成功的话返回一个新的fd,然后服务器就可以通过这个新的fd和客户端进行通讯。如果失败返回 -1;

          (5)对数据的操作(收,发)

          (6)关闭

客户端:

1.建立套接字

2.链接服务器

        connect(int sockfd, const struct sockaddr *addr,socklen_t addrlen);
        第一个参数:就是第一步新建的socket返回的fd。
        第二个参数:指定你要链接的服务器的地址(IP+PORT)
        第三个参数:这个地址的长度。

3.对数据操作(收,发)

4.关闭

今日代码:

/*************************************************************************
    > File Name: server1.c  服务器
    > Author: csgec
    > Mail: [email protected] 
    > Created Time: Tue 31 Jul 2018 03:50:36 PM HKT
 ************************************************************************/

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

int main()
{
    int serverfd;
    int clientfd;
    int ret;

    serverfd = socket(AF_INET,SOCK_STREAM,0);//建立套接字
    if(serverfd < 0)
    {
        perror("socket crate fail\n");
        return -1;
    }

    struct sockaddr_in serveraddr;
    struct sockaddr_in clientaddr;

    memset(&serveraddr,0,sizeof(serveraddr));
    memset(&serveraddr,0,sizeof(serveraddr));

    serveraddr.sin_family = AF_INET;
    serveraddr.sin_addr.s_addr = INADDR_ANY;//ip地址,表示接受任意ip的请求
    serveraddr.sin_port = htons(8000);//表示对应的端口号,客户端就可以通过这个端口通讯

    //绑定通讯地址
    ret = bind(serverfd,(struct sockaddr *)&serveraddr,sizeof(struct sockaddr_in));
    if(ret < 0)
    {
        perror("bind fail");
        return -1;
    }

    //监听
    ret = listen(serverfd,10);
    if(ret < 0)
    {
        perror("listen fail");
        return -1;
    }
    
    int sin_size = sizeof(struct sockaddr_in);
    //接受链接
    clientfd = accept(serverfd,(struct sockaddr *)&clientaddr,&sin_size);
    if(clientfd < 0)
    {
        perror("accept faile");
        close(serverfd);
        return -1;
    }


    char buf[128];
    memset(buf,0,128);

    while(1)//对数据收发操作
    {
        printf("请给客户机发一条消息:");
        scanf("%s",buf);
        send(clientfd,buf,strlen(buf),0);

        memset(buf,0,128);

        recv(clientfd,buf,128,0);
        printf("客户机回复说:");
        printf("%s\n",buf);

        if(strcmp(buf,"quit") == 0)
        {
            break;
        }
    }
    close(serverfd);
    close(clientfd);
}

/////////////////////////////////////////////////////////////////////////////

/*************************************************************************
    > File Name: kehuji1.c  客户机
    > Author: csgec
    > Mail: [email protected] 
    > Created Time: Tue 31 Jul 2018 03:50:36 PM HKT
 ************************************************************************/

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

int main()
{
    int serverfd;
    int clientfd;
    int ret;

    serverfd = socket(AF_INET,SOCK_STREAM,0);//建立套接字
    if(serverfd < 0)
    {
        perror("socket crate fail\n");
        return -1;
    }
    struct sockaddr_in serveraddr;

    memset(&serveraddr,0,sizeof(serveraddr));//清空结构体

    //初始化
    serveraddr.sin_family = AF_INET;

    serveraddr.sin_addr.s_addr = INADDR_ANY;//ip地址,表示接受任意ip的请求
    serveraddr.sin_addr.s_addr = inet_addr("127.0.0.1");//ip地址,表示接受任意ip的请求
    serveraddr.sin_port = htons(8000);//表示对应的端口号,客户端就可以通过这个端口通讯

    ret = connect(serverfd,(struct sockaddr *)&serveraddr,sizeof(struct sockaddr));
    if(ret < 0)
    {
        perror("connect fail\n");
        close(serverfd);
        return -1;
    }

    char buf[128];
    memset(buf,0,128);
    while(1)//对数据收发操作
    {
        printf("收到服务器的数据为:");
        recv(serverfd,buf,128,0);
        printf("%s\n",buf);

        memset(buf,0,128);
        printf("请给服务器回信:");
        scanf("%s",buf);
        send(serverfd,buf,strlen(buf),0);
        if(strcmp(buf,"quit") == 0)
        {
            break;
        }
    }
    close(serverfd);
}
 

猜你喜欢

转载自blog.csdn.net/qq_37589838/article/details/81321108