Linux—网络编程(day12)

强颜欢笑 提交于 2020-02-22 03:29:42

一、网络基础知识

二、基于TCP的网络编程

 


 

二、基于TCP的网络编程

 

1、编程中用到的辅助函数

(1)主机字节序和网络字节序的转换

  因为数据存储方式涉及大端和小端,不同方式通信时需要转换,网络字节序为大端;可以使用以下函数:

  #include<arpa.inet.h>

  uint32_t htonl(uint_32_t hostlong);

  uint16_t htons(uint_16_t hostshort);

  uint32_t ntohl(uint_32_t netlong);

  uint16_t nonhs(uint_16_t hostshort);

  其中:h代表host,n代表net,l代表long,s代表short

(2)具体的网络协议地址空间和通用的网络地址空间的转换。

  具体的网络协议族有ipv4,ipv6,local,unix等,各自有各自的地址空间,通用地址空间的类型为 struct sockaddr类型,在bind,accept等函数中都要用此类型做参数,可使用以下函数做转换:

 

  inet_pton(3)

  int inet_pton(int af, const char *src, void *dst);

功能:

  转换src(点分十进制的地址格式)指定的字符串为网络地址结构到af指定的网络地址家族(即text to binary),并拷贝网络地址结构到dst中,af必须指定为AF_INET或者AF_INET 6之一。

参数:

  af:

    AF_INET

    AF_INET6

  src:点分十进制的字符串IP地址

  dst:转换后的内容,struct in_addr类型(根据af指定协议转换后格式不同,此处以AF_INET为例)

返回值:

  成功:1

  src不可用:0

  af不可用:-1,errno被设置为EAFNO_SUPPORT

 

 

 inet_ntop(3)

const char * inet_ntop(int af, const void *src, char *dst, socklen_t size);    //将数值格式转化为点分十进制的ip地址格式

功能:

  将在af指定的网络地址空间的src转换为字符串,即将ipv4或ipv6地址从二进制转换到文本结果被拷贝到dst(非空)指定的缓冲区中

参数:

  

 af:

   AF_INET

   AF_INET6

 src:

  如果指定为AF_INET,则该类型为struct in_addr

 dst:

  字符串地址空间

 size:

  指定了buffer的有效字节数

返回值:

  错误:NULL,errno被设置

  成功:指向dst的空间的地址

 

 

(3)ipv4的sockaddr_in结构体

struct sockaddr_in{

  sa_family_t sin_family AF_INET.

  in_port_t sin_port Port number.

  struct in_addr sin_addr IP address.

}

另外;struct in_addr至少要包含in_addr_t  s_addr这个成员

struct sockaddr_in{

  in_addr_t  s_addr;//无符号32位,在inttypes.h中被定义

}

 2、基于TCP的客户端编程

(1)使用socket(2)创建铜须描述符

(2)使用bind(2)绑定端口号与IP地址

(3)使用connect(2)链接服务器

(4)数据发送接收

(5)等待服务器相应

(6)关闭服务器连接

connect(2)返回代表客户端的三次握手结束,accept(2)的返回代表服务器的三次握手结束

connect(2)

int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen)

功能:

  把sockfd指定的socket连接到addr指定的地址空间

参数:  

  sockfd:socket(2)的返回值

  addr:要连接的服务器的地址空间,格式由sockfd决定

  addrlen:addr的大小

返回值:

  成功:0

  失败:-1,errno被设置

返回:若成功则为0,若出错则为-1

 

基于TCP服务器代码:

#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <arpa/inet.h>
int main()
{
int listenfd = socket (AF_INET, SOCK_STREAM, 0);
if (listenfd == -1)
    {
        perror ("socket");
        exit (EXIT_FAILURE);
    }
struct sockaddr_in addr;
    addr.sin_family = AF_INET;
    addr.sin_port = htons (8888);
    addr.sin_addr.s_addr = INADDR_ANY;
if (bind (listenfd, (struct sockaddr*)&addr, sizeof (addr)) == -1)
    {
        perror ("bind");
        exit (EXIT_FAILURE);
    }
if (listen (listenfd, 1024) == -1)
    {
        perror ("listen");
        exit (EXIT_FAILURE);
    }
struct sockaddr_in addrcli = {};
    socklen_t addrlen = sizeof (addrcli);
int connfd = accept (listenfd, (struct sockaddr*)&addrcli, &addrlen);
if (connfd == -1)
    {
        perror ("accept");
        exit (EXIT_FAILURE);
    }
    printf ("服务器已接受来自%s:%hu客户机的连接请求\n", inet_ntoa (addrcli.sin_addr),ntohs (addrcli.sin_port));
char buf[1024];
    ssize_t rcvd = recv (connfd, buf, sizeof (buf), 0);
if (rcvd == -1)
    {
        perror ("recv");
        exit (EXIT_FAILURE);
    }
if (rcvd == 0)
    {
        printf ("客户机已关闭连接\n");
        exit (EXIT_FAILURE);
    }
    buf[rcvd] = '\0';
    printf ("客户端说:%s\n", buf);
    printf ("服务器说:");
    gets (buf);
    ssize_t sent = send (connfd, buf, strlen (buf) * sizeof (buf[0]), 0);
if (sent == -1)
    {
        perror ("send");
        exit (EXIT_FAILURE);
    }
if (close (listenfd) == -1)
    {
        perror ("close");
        exit (EXIT_FAILURE);
    }
if (close (connfd) == -1)
    {
        perror ("close");
        exit (EXIT_FAILURE);
    }
return 0;
}

 

基于TCP的客户端代码:

#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <arpa/inet.h>
int main()
{
int listenfd = socket (AF_INET, SOCK_STREAM, 0);
if (listenfd == -1)
    {
        perror ("socket");
        exit (EXIT_FAILURE);
    }
struct sockaddr_in addr;
    addr.sin_family = AF_INET;
    addr.sin_port = htons (8888);
    addr.sin_addr.s_addr = inet_addr("127.0.0.1");
if (connect (listenfd, (struct sockaddr*)&addr, sizeof (addr)) == -1)
    {
        perror ("connect");
        exit (EXIT_FAILURE);
    }
char buf[1024] = "你好,服务器";
    printf ("客户端说:%s\n", buf);
    ssize_t sent = send (listenfd, buf, strlen (buf) * sizeof (buf[0]), 0);
if (sent == -1)
    {
        perror ("send");
        exit (EXIT_FAILURE);
    }
    ssize_t rcvd = recv (listenfd, buf, sizeof (buf), 0);
if (rcvd == -1)
    {
        perror ("recv");
        exit (EXIT_FAILURE);
    }
    buf[rcvd] = '\0';
    printf ("服务器说:%s\n", buf);
if (close (listenfd) == -1)
    {
        perror ("close");
        exit (EXIT_FAILURE);
    }
return 0;
}

 

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!