Linux 操作系统网络编程2

2024-05-09 18:04

本文主要是介绍Linux 操作系统网络编程2,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

1、TCP服务器编写流程

头文件:

#include <sys/socket.h>

1.1 创建套接字

函数原型:

int socket(int domain, int type, int protocol);

参数:

        domain: 网域
               AF_INET : IPv4
               AF_INET6 : IPv6
               AF_UNIX : 本地通讯

type:选择传输协议  tcp/udp

                SOCK_STREAM ; tcp
                SOCK_DGRAM : udp

protocol: 基本废弃, 一般赋 0
返回值: 成功返回描述网络套接字 sockfd, 失败返回-1
举例: 创建描述网络的套接字:

int sfd = socket(AF_INET,SOCK_STREAM,0);

1.2 绑定

头文件:

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

作用:绑定一个端口和IP地址,使套接口与指定的端口号和IP地址相关联

函数原型:

int bind(int sockfd, const struct sockaddr *my_addr, socklen_t addrlen);

参数:

        sockfd 为前面 socket 的返回值, 描述网络的套接字
        my_addr:封装 ip 地址和端口号

struct sockaddr //一般很少用
{unsigned short int sa_family; // AF_INET。char sa_data[14]; //IP 和端口
};
struct sockaddr_in //常用的结构体
{unsigned short int sin_family; //AF_INEuint16_t sin_port; //使用的 port 编号struct in_addr sin_addr; // IP 地址unsigned char sin_zero[8]; //未使用
};

端口:10000-65535之间随意选

转化:

uint32_t htonl(uint32_t hostlong);//本函数将一个 32 位数从主机字节顺序转换成无符号长整型网络字节顺序
uint16_t htons(uint16_t hostshort);//将一个无符号短整型的主机数值转换为网络字节顺序
uint32_t ntohl(uint32_t netlong);//将一个无符号长整形数从网络字节顺序转换为主机字节顺序。
uint16_t ntohs(uint16_t netshort);//将一个 16 位数由网络字节顺序转换为主机字节顺序。

IP的填写方式:

struct in_addr
{uint32_t s_addr; //=inet_addr("192.168.1.22");
};

返回值:成功则返回0,失败返回-1

举例:

#define PORT 33333
#define IP "192.168.110.123"
struct sockaddr_in ser_addr;
ser_addr.sin_family = AF_INET;
ser_addr.sin_port = htons(PORT);
ser_addr.sin_addr.s_addr = inet_addr(IP);
inet_aton(“192.168.1.22”,&ser_addr.sin_addr);
bind(sfd,(struct sockaddr)&ser_addr,sizeof(ser_addr));

1.3 监听

作用:设置允许的最大连接数(瞬间处理的阀值),listen函数。

使用服务器的这个端口和IP处于监听状态,等待网络中某一客户机的连接请求。如果客户端哟连接请求,端口就会接受这个链接。

函数原型:

int listen(int sockfd, int backlog);

参数:

        sockfd 为前面 socket 的返回值, sfd
        backlog 指定同时能处理的最大连接要求, 通常为 10 或者 5。 最大值可设至 128( 不是最多可以连接 128个客户端, 是一个瞬时处理的阈值)
返回值: 成功则返回 0, 失败返回-1

1.4 等待客户端连接

函数原型:

int accept(int sockfd, struct sockaddr *addr,socklen_t *addrlen);

参数:

        sockfd 为前面 socket 的返回值, 即 sfd
        addr: 提供空间, 用于接受客户端的 ip 地址和端口号
        addrlen: 第二个参数大小

返回值:

        返回新的套接字描述符, 专门用于与建立的客户端通信
        失败-1;

举例:

struct sockaddr_in cli_addr = {0};
socklen_t len = sizeof(cli_addr);
int cfd = accept(sfd,(struct sockaddr *)&cli_addr,&len);

1.5 读写函数

可以使用read和write函数进行。

写函数

函数原型;

ssize_t send(int s, const void *buf, size_t len, int flags);

参数:

        s: 通信套接字
        buf: 要发送的数据缓冲区
        len: 数据长度
        flags: 一般赋 0 .阻塞

返回值:成功返回真正发送的数据长度,失败-1.

读函数

函数原型:

ssize_t recv(int s, void *buf, size_t len, int flags);

参数:

        s: 通信的套接字
        buf:存放接收数据的缓冲区
        len: 数据长度
        flags: 一般赋 0 .阻塞

返回值:成功返回真正接收的数据长度,失败-1.

2 TCP客户端编写流程

2.1 创建套接字

头文件:

#include <sys/socket.h>

函数原型:

int socket(int domain, int type, int protocol);

参数:

        domain: 网域
                AF_INET : IPv4
                AF_INET6 : IPv6
        type: 选择传输协议 tcp /udp
                SOCK_STREAM ; tcp
                SOCK_DGRAM : udp
        protocol: 基本废弃, 一般赋 0

返回值:成功返回套接字fd,失败返回-1

2.2 连接

函数原型:

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

参数:

    sockfd 为前面 socket 的返回值, 即 fdserv_addr 为结构体指针变量, 存储着远程服务器的 IP 与端口号信息。addrlen 表示结构体变量的长度

返回值:成功则返回0,失败返回-1

举例:

    int fd = socket(AF_INET,SOCK_STREAM,0);#define PORT 33333#define IP "192.168.110.123"struct sockaddr_in ser_addr;ser_addr.sin_family = AF_INET;ser_addr.sin_port = htons(PORT);ser_addr.sin_addr.s_addr = inet_addr(IP);connect(fd,(struct sockaddr *)&ser_addr,sizeof(ser_addr));

TCP 问题: 当服务器结束之后, 再次运行会出现 bind 错误(地址被占用)
解决办法:

      int sfd = socket(AF_INET,SOCK_STREAM,0);


创建套接字之后, 用:

int val = 1;
setsockopt(sfd,SOL_SOCKET,SO_REUSEADDR,&val,sizeof(val));
setsockopt(sfd,SOL_SOCKET,SO_REUSEPORT,&val,sizeof(val));

3.UDP

特点:非面向连接,不可靠传输,传输速率高

分别有:

单播  --  一对一                广播  --  一对多          组播  --  多对多

3.1 单播

        UDP不像TCP。无需在连接状态下交换数据,因此基于UDP的接收方和发送发也无需经过连接过程。也就是说,不必调用listen()和accept()函数。UDP中有创建套接字的过程和数据交换的过程。不管是接收方还是发送方都只需要1个套接字。

3.1.1 创建套接字
头文件:

#include <sys/socket.h>

函数原型:

int socket(int domain, int type, int protocol);

参数:

        domain: 网域
        AF_INET : IPv4
        AF_INET6 : IPv6
        type: 选择传输协议 tcp /udp
        SOCK_STREAM ; tcp
        SOCK_DGRAM : udp
        protocol: 基本废弃, 一般赋 0
返回值: 成功返回套接字 fd, 失败返回

3.1.2 bind:绑定自己的IP和端口

发送方:socket   同接收方

函数原型:

ssize_t sendto( int s, //套接字const void *buf, //要发送的数据的首地址size_t len, //数据的大小int flags, // 0const struct sockaddr *to,//接收方的 IP 和 portsocklen_t tolen //上一个参数的大小
);

返回值:成功返回真正发送的数据长度,失败-1

ssize_t recvfrom(int s, //套接字void *buf, //接受的内容存放的位置的首地址size_t len, //接收的大小int flags, //0struct sockaddr *from, //提供空间即可, 存放发送方的 IP 和 PORTsocklen_t *fromlen//上一个参数的大小, 但是填指针
);

返回值:成功返回真正接收的数据长度, 失败-1

3.2 广播

udp具有广播功能,即一个发送方,多个接收方;

广播:处于局部网络中的所有设备都可以接收消息

广播的地址:网络号不变,主机号为255 

socket 创建的 UDP 套接字支持组播和广播, 但是想要使用广播, 必须用 setsockopt 设置广播的功能。

接收方:
        1》 创建套接字 socket UDP
        2》 绑定 IP 和 PORT IP 填 INADDR_ANY
        3》 recvfrom 接收

发送方:

        1》 创建套接字 socket UDP
        2》 开启广播功能: setsockopt

开启广播功能函数

int setsockopt(int sockfd,int level,int optname,const void *optval,socklen_t optlen);

函数功能:设置套接字的选项

参数:

sockfd创建的套接字

        level--选项所在的级别:
        想让套接字有广播功能, 就必须把 level 设置为 SOL_SOCKET
                SOL_SOCKET -- 广播功能所在的级别
        optname--选项所在的名称:
                SO_BROADCAST (广播功能)
        optval: 整数的地址
                int num = 1;//开启功能 &num
                0--失能(关闭此功能,系统默认关闭)
                1--使能(开启此功能)
        optlen: optval 的大小 //sizeof(num);

举例:

int a = 1;
setsockopt(fd,SOL_SOCKET,SO_BROADCAST,&a,sizeof(int));

sendto 发送


3.3 多播

对一组特定的主机发送消息 比如: 直播, 多播(D 类), IP 地址分为: 224.0.0.0~239.255.255.255

1》 创建套接字 socket UDP
 

 int setsockopt(int sockfd, int level, int optname,const void *optval, socklen_t optlen);

函数功能: 设置套接字的选项
参数:
        sockfd: socket 创建的套接字
        level: 级别
        SOL_SOCKET : 广播级别
        IPPROTO_IP : 组播级别

        optname: 选项由 level 决定, level 选的是 IPPROTO_IP, optname 有两种选择
        IP_ADD_MEMBERSHIP 加入组播
        IP_MULTICAST_IF 创建组播
        optval: 设置参数 由 optname 决定
        当 optname 为:
                IP_ADD_MEMBERSHIP( 加入组播) , optval 是 struct ip_mreqn 这个结构体
                IP_MULTICAST_IF ( 创建组播) , optval 也是 struct ip_mreqn 这个结构体

struct ip_mreqn
{struct in_addr imr_multiaddr;//多播组的地址 224.0.0.0-239.255.255.255 structin_addr imr_address;//本地的 IP 地址, 填固定的宏 INADDR_ANY 即可int imr_ifindex; //网卡编号( 物理硬件地址) , 可以用物理硬件 ID 函数:                                                     if_nametoindex("ens33"); 其中 ens33 是网卡的
名字, 通过名字获取编号
};

这篇关于Linux 操作系统网络编程2的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/974105

相关文章

java并发编程之CyclicBarrier(循环栅栏)

package com.zhong;import java.util.concurrent.CyclicBarrier;/*** Cyclic意思是循环,Barrier意思是屏障,那么CyclicBarrier翻译过来就是循环栅栏。* 它是一个同步辅助类,能让一组线程互相等待,* 直到这一组线程都到了一个公共屏障点,各线程才能继续向下执行。因为该屏障能够在释放等待线程后继续重用,所以叫循环屏障。*

Linux命令学习之二

每日一结 ​               命令置换:是将一个命令的输出作为另一个命令的参数,命令格式如下: commond1 `command2` 其中,命令command2的输出将作为命令command1的参数,需要注意的是, 命令置换的单引号为ESC键下方的 ` 其意思就是说,先运行单引号内的命令,再将其命令作为

Linux命令学习之一

每日一结                                                                                        注:当用户不确定一个软件包的类型时, 可使用file命令查看文件类型

Linux文件I/O之一

每日一结(标准I/O)   一  库    本质 :一组实现函数接口 [printf,scanf,strcpy,strlen]   使用标准库好处:屏蔽底层细节,向上层提供统一的接口,提高程序的可移植性   windows 库 : *.dll  linux   库 : *.so    二 系统调用接口    本

嵌入式C和汇编混合编程规则——ATPCS规则

ATPCS规则  为了使单独编译的C语言程序和汇编程序之间能够相互调用,必须为子程序之间的调用规定一定的规则.ATPCS就是ARM程序和THUMB程序中子程序调用的基本规则。 一.ATPCS概述 ATPCS规定了一些子程序之间调用的基本规则.这些基本规则包括子程序调用过程中寄存器的使用规则,数据栈的使用规则,参数的传递规则.为适应一些特定的需要,对这些基本的调用规则进行一些修改得到几种不

Linux网络编程之五

每日一结 组播: ​ 网络地址: 一些特殊的组播地址:   一 组播包收和发 1.发送方 (1)创建用户数据报套接字 (2)填充组播地址和端口  (3)发送数据到组播地址 2.接收方  (1)创建用户数据报套接字 (2)加入组播组  struct ip_mreq mreq; mreq.imr_m

Linux网络编程之四

每日一结 一 UDP并发  核心思想:父进程接收到客户端的数据,就创建子进程,在子进程中创建一个新的套接字  和客户端交互  int do_client(接受客户端地址,数据,数据长度) { 1.创建用户数据报套接字  2.自动分配地址  3.处理数据[例如:输出数据内容] 4.通过新创建的套接字将数据回发给客户端  w

Linux网络编程之三

每日一结 Tftp服务器的实现: server.c ​       client.c     代码分析如下:     一 Linux IO模型  (1)阻塞IO  (2)非阻塞IO  非阻塞IO

Linux网络编程之二

每日一结   一 TCP 函数接口  int listen(int sockfd, int backlog); 功能:设置流式套接字为监听模式  参数: @sockfd    流式套接字的fd  @backlog   请求队列的长度,最大128  返回值: 成功返回0,失败返回-1    int accept(i

Linux网络编程之一

每日一结 一 网络基础知识 (一)IP地址 1.IP   :网络中一台主机唯一标识  2.组成 :网络号 + 主机号  3.IP 分类 最高位    第一个字节 A  1 + 3     0        [0-127]     B  2 + 2    10        [128-191]