首页 > 系统相关 >Linux网络编程2

Linux网络编程2

时间:2024-08-05 22:59:50浏览次数:17  
标签:sockaddr addr int 编程 网络 Linux 接字 客户端 函数

TCP编程

顺序图

socket() 函数

socket()函数用于创建一个新的套接字。它是进行网络编程的第一步,因为所有的网络通信都需要通过套接字来进行。

原型:

#include <sys/socket.h>  

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

    domain:指定协议族,对于TCP/IP网络,它通常是AF_INET(IPv4)或AF_INET6(IPv6)。
    type:指定套接字类型,对于TCP连接,它通常是SOCK_STREAM。
    protocol:指定协议,通常对于AF_INET和SOCK_STREAM,协议为0,表示使用TCP协议。

返回值:成功时返回一个非负整数(套接字描述符),失败时返回-1,并设置errno。

bind() 函数

bind()函数用于将套接字与特定的IP地址和端口号绑定起来。这样,服务器就可以在这个特定的IP地址和端口上监听客户端的连接请求。

原型:

#include <sys/socket.h>  

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

    sockfd:通过socket()函数创建的套接字描述符。
    addr:指向sockaddr结构的指针,该结构包含IP地址和端口号。对于IPv4,通常使用sockaddr_in结构。

addr:采用struct sockaddr的结构体地址,通用结构体

struct sockaddr

{

        sa_family_t sa_family;

        char sa_data[4];

}

struct sockaddr_in

{         基于Internel通信结构体

        as_family_t sin_family;

        in_port_t sin_port;

        struct in_addr sin_addr;

        sin_zero , //填充字节,需清零

}

struct in_addr

{

        uint32_t s_addr;

}

    addrlen:addr参数指向的地址结构的长度。

返回值:成功时返回0,失败时返回-1并设置errno。

举个例子

其中注释

  • 使用socket()函数创建一个TCP套接字,并将其描述符存储在server_fd中。
  • 使用memset()函数将server_addr结构清,以确保所有未明确设置的字段都被初始化为0。
  • 设置server_addr结构的sin_familyAF_INET,表示使用IPv4地址。
  • sin_addr.s_addr设置为INADDR_ANY,这表示服务器将监听所有可用的网络接口。
  • 使用htons()函数将端口号从主机字节序转换为网络字节序,并将其存储在sin_port中。
  • 使用bind()函数将套接字server_fdserver_addr指定的地址和端口绑定。
  • 注意:示例中没有实现监听连接和接受连接的代码,这些通常通过listen()accept()函数来完成。
  • 最后,使用close()函数关闭套接字以释放资源。

关于使用bind函数的结构体

bind()函数的调用中,你需要将sockaddr_in结构体的地址(即一个指向该结构体的指针)作为参数传递。你通过取地址操作符&来获取这个地址,并将其强制转换为struct sockaddr *类型(因为bind()函数的原型要求这个参数是struct sockaddr *类型,这是一个更通用的套接字地址结构体指针,sockaddr_in是它的一个特例)。

同时,你需要传递结构体的大小作为bind()函数的第三个参数。这是为了确保函数能够正确地解释传递给它的地址信息。你使用sizeof(server_addr)来获取这个大小。

listen() 函数

listen() 函数用于将套接字设置为监听状态,以接受连接请求。一旦套接字被设置为监听状态,它就可以接受来自客户端的连接请求。

函数原型:

#include <sys/socket.h> 

int listen(int sockfd, int backlog);

    sockfd:是之前通过socket()函数创建的套接字描述符。
    backlog:指定了内核应该为相应套接字排队的最大连接个数。当多个客户端同时尝试连接时,这个参数限制了可以处于半连接状态(即收到SYN包,但还未收到客户端确认的ACK包)的TCP连接的数量。注意,实际可排队的连接数可能会小于请求数,这取决于系统限制。(内核中的服务器的套接字fd会维护2个链表:1正在三次握手的客户端链表(数量=2*backlog+1)2已经完成三次握手分配好了的newfd)。如:listen(fd,5);//表示系统允许11(5*2+1)个客户同时进行三次握手

返回值:成功时返回0;失败时返回-1,并设置errno以指示错误。

accept() 函数

accept() 函数用于接受一个连接。当套接字处于监听状态时,accept() 函数会阻塞(除非套接字被设置为非阻塞模式),直到一个连接请求到达。一旦连接被接受,accept() 会创建一个新的套接字描述符,用于与连接的客户端进行通信,而原始的套接字描述符(即传递给listen()的那个)则继续用于监听新的连接请求。

函数原型:

#include <sys/socket.h> 

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

    sockfd:是之前通过socket()函数创建的并已经通过listen()设置为监听状态的套接字描述符。
    addr:是一个指向sockaddr结构的指针,该结构用于返回连接客户端的地址信息(可以用作查找客户机)。如果不需要客户端的地址信息,可以设置为NULL。
    addrlen:是一个指向socklen_t的指针,用于传入addr结构的大小,并在函数返回时更新为实际返回的地址信息的大小。

返回值:成功时返回一个新的套接字描述符,用于与连接的客户端通信;失败时返回-1,并设置errno以指示错误。

案例(四个函数一起使用):

关于上述的最后输出的printf("Connection accepted from %s:%d\n"inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port));

inet_ntoa()ntohs() 是两个用于网络编程的函数,它们分别用于将网络字节序(network byte order)转换为主机字节序(host byte order)的不同表示形式(socket函数介绍中有提到)。

inet_ntoa()用于将网络地址(通常是IPv4地址)从网络字节序的二进制形式转换为点分十进制字符串表示(例如,将 192.168.1.1 的二进制形式转换为文本字符串 "192.168.1.1")。

ntohs() 则是专门用于将无符号短整型(通常是端口号)从网络字节序转换为主机字节序。

通过上述学习的函数就可以成功写出一个简单的服务器端的代码,如下

如若要写客户端的代码,还需学习一个connect()函数

connect()函数

在网络编程中,connect 函数是一个非常重要的函数,它用于客户端程序来建立一个到服务器的连接。这个函数通常在套接字(socket)编程中使用,特别是在使用TCP协议时。connect 函数尝试将客户端的套接字与服务器上的套接字(或称为端口)建立连接。
函数原型:

在C语言(以及许多其他支持网络编程的语言)中,connect 函数的原型通常如下所示:

#include <sys/types.h>  
#include <sys/socket.h> 

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

参数说明

    sockfd:这是由socket函数返回的套接字描述符,代表客户端的套接字。
    addr:这是一个指向sockaddr结构(或其变体,如sockaddr_in用于IPv4)的指针,该结构包含了服务器的地址和端口信息。
    addrlen:这是addr参数所指向的结构的长度,以字节为单位。这允许connect函数知道它应该读取多少字节的地址信息。

返回值:

    成功时,connect函数返回0。
    出错时,返回-1,并设置全局变量errno以指示错误类型。

代码如下

实现功能如下

即一发一收,实现数据传递

这个代码可以被优化

下图修改了获取地址,通过这样可以自动搜索地址,无需宏定义地址

原代不能获取客户端的信息,修改之后通过accept()函数获取了客户端的地址与端口号信息

也能实现同样的功能

标签:sockaddr,addr,int,编程,网络,Linux,接字,客户端,函数
From: https://blog.csdn.net/2302_81386929/article/details/140924169

相关文章

  • linux运维一天一个shell命令之tcpdump详解
    一、tcpdump的概念tcpdump是一个数据包捕获工具,能够拦截和显示通过网络接口的数据包。它可以实时捕获数据包,也可以将捕获的数据保存到文件中以便后续分析。tcpdump支持基于多种条件(如IP地址、端口号、协议等)来捕获特定的数据包。二、主要功能和特点1.数据包捕获:tcp......
  • 网络安全学习之DVWA平台的搭建及简单使用
    DVWA介绍DVWA(DamnVulnerableWebApplication)是一个用来进行安全脆弱性鉴定的PHP/MySQLWeb应用,旨在为安全专业人员测试自己的专业技能和工具提供合法的环境,帮助web开发者更好的理解web应用安全防范的过程。DVWA一共包含了十个攻击模块,分别是:BruteForce(暴力(破解))、Comm......
  • 仓颉编程语言入门 -- Array数组详解
    仓颉编程语言入门–Array数组详解一.如何创建Array数组我们可以使用Array类型来构造单一元素类型,有序序列的数据。1.仓颉使用Array来表示Array类型。T表示Array的元素类型,T可以是任意类型,类似于泛型的概念vararr:Array<String>=["你好","仓颉"]va......
  • 2024 睿抗机器人开发者大赛CAIP-编程技能赛-本科组(国赛)
    2024睿抗机器人开发者大赛CAIP-编程技能赛-本科组(国赛)前言补题只补了前四道,第五题打个暴力都有\(24\)分,我这死活只有\(22\)分\(QAQ\)RC-u1大家一起查作弊思路按题意模拟。不过很奇怪赛时用getline老是读入不了,还好换成cin直接读也问题不大。代码#include<bits......
  • Linux——线程互斥与同步
    一、线程互斥1.1线程间互斥的概念在学习管道的时候,管道是自带同步与互斥的。而在线程中,当多个线程没有加锁的情况下同时访问临界资源时会发生混乱。在举例之前,先了解几个概念。临界资源:多个线程执行流共享的资源叫做临界资源临界区:每个线程内部访问临界资源的代码叫做临界......
  • Kali Linux 安装
    KaliLinux安装前言1、KaliLinux基本介绍(1)KaliLinux的起源和前身(2)Debian系与Redhat系区别(3)下载和安装kali1.下载Kali2.解压压缩包3.打开kali镜像4.修改root密码(4)修改语言为中文(5)替换ATP源(6)配置远程连接(7)启动SSH服务(8)更新kali下期前言本期主要学习了Kali的基......
  • 面向城市人群流量预测的深度时空残差网络[名词解释]
    [1]端到端的结构:输入直接映射到输出,没有中间步骤或人为干预。这种方法的核心思想是将整个任务或流程作为一个单一的系统来优化和执行,而不需要手动处理中间步骤或特征工程。[2]残差神经网络残差的使用主要是由于直接进行学习容易导致梯度的爆炸或消失,使用残差块,不直接学习映......
  • 驱动开发系列09 - Linux设备模型之设备,驱动和总线
    一:概述     Linux设备模型(LDM)是Linux内核中引入的一个概念。用于管理内核对象(那些需要引用计数的对象、例如文件、设备、总线甚至驱动程序),以及描述它们之间的层次结构,以及这些内核对象之间绑定关系。Linux设备模型引入了对象生命周期管理、引用计数、以及面向对象......
  • 【算法】浅析网络流算法
    网络流算法:优化资源分配,提升网络效率1.引言在网络科学、运筹学以及计算机科学等领域,网络流算法是一个重要的研究对象。它关注如何在网络中高效地分配资源,以实现最大流、最小费用流等目标。本文将带你了解网络流算法的原理、使用方法及其在实际应用中的意义,并通过代码示例......
  • [20240804]关于kitty设置与linux LANG环境设置问题.txt
    [20240804]关于kitty设置与linuxLANG环境设置问题.txt--//更正我以前理解的一个混沌的地方:--//我以前个人的工作习惯:LANG=en_US,kittyRemotecharacterset选择Usefontencoding.--//目前这样的设置存在一些问题:--//kitty设置LANG=en_US.UTF-8的情况下,kittywindow->Trans......