Linux C高级编程——网络编程之API(5)

Linux C网络编程——API


宗旨:技术的学习是有限的,分享的精神的无限的。

        

一、基本socket函数

        Linux系统是通过提供套接字(socket)来进行网络编程的。网络的socket数据传输是一种特殊的I/O,socket也是一种文件描述符。socket也有一个类似于打开文件的函数:socket(),调用socket(),该函数返回一个整型的socket的描述符,随后的连接建立、数据传输等操作也都是通过该socket实现。

1socket函数

       ——创建套接字

(1)函数原型

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

(2)函数参数

        domain指明所使用的协议族,通常为PF_INET,表示TCP/IP协议;

        type参数指定socket的类型,基本上有三种:数据流套接字、数据报套接字、原始套接字

        protocol通常赋值"0"。

(3)返回值

        调用成功,返回socket文件描述符;失败,返回-1,并设置errno

        两个网络程序之间的一个网络连接包括五种信息:通信协议、本地协议地址、本地主机端口、远端主机地址和远端协议端口。socket数据结构中包含这五种信息。

2bind函数

       ——将套接字和指定的端口相连

(1)函数原型

struct sockaddr_in
{short intsin_family;unsignedshort int sin_port;structin_addr sin_addr;unsignedchar sin_zero[8];
}; // addrlen为sockaddr的长度。int bind(int sock_fd, struct sockaddr_in *my_addr, int addrlen);

(2)函数参数

        sock_fd是调用socket函数返回值;

        my_addr是一个指向包含有本机IP地址及端口号等信息的sockaddr类型的指针;

  struct sockaddr_in结构类型是用来保存socket信息的。

(3)返回值

        成功返回0,否则,返回-1,并置errno。  

3connect函数

       ——客户端发送服务请求

(1)函数原型

        int connect(int sock_fd, struct sockaddr*serv_addr,int addrlen);

(2)函数参数

        sock_fd 是socket函数返回的socket描述符;

        serv_addr是包含远端主机IP地址和端口号的指针;

        addrlen是结构sockaddr_in的长度。

(3)返回值

        成功返回0,否则返回-1,并置errno。

4listen函数

        ——等待指定的端口的出现客户端连接

(1)函数原型

        int listen(int sock_fd, int backlog);

(2)函数原型

        sock_fd 是socket()函数返回值;

        backlog指定在请求队列中允许的最大请求数

(3)返回值

        调用成功返回0,否则,返回-1,并置errno.

5accecpt函数

       ——用于接受客户端的服务请求

(1)函数原型

        int accept(int sock_fd, struct sockadd_in* addr, int addrlen);

(2)函数参数

        sock_fd是被监听的socket描述符,

        addr通常是一个指向sockaddr_in变量的指针,

        addrlen是结构sockaddr_in的长度。

(3)返回值

        成功返回新的套接字描述符,失败返回-1,并置errno。

6write函数

        ——write函数将buf中的nbytes字节内容写入文件描述符

(1)函数原型

        ssize_t write(int fd,const void *buf,size_t nbytes);

(2)函数参数

       fd:套接字

       buf:要写入的数据

       nbytes:字节数

(3)返回值   

        成功时返回写的字节数.失败时返回-1. 并设置errno变量.

在网络程序中,当我们向套接字文件描述符写时有俩种可能:

 (1)write的返回值大于0,表示写了部分或者是全部的数据.

(2)返回的值小于0,此时出现了错误.需要根据错误类型来处理.  如果错误为EINTR表示在写的时候出现了中断错误.  如果错误为EPIPE表示网络连接出现了问题.

7read函数

       ——read函数是负责从fd中读取内容

(1)函数原型

        ssize_t read(int fd,void *buf,size_t nbyte)

(2)函数参数

       fd:套接字

       buf:存放要读出的数据

       nbytes:字节数

(3)返回值

        当读成功时,read返回实际所读的字节数,如果返回的值是0 表示已经读到文件的结束了,小于0表示出现了错误。如果错误为EINTR说明读是由中断引起的,如果错误是ECONNREST表示网络连接出了问题。

8close函数

        ——关闭socket

(1)函数原型

        int close(sock_fd);

(2)函数参数

        sock_fd:套接字

(3)返回值

        函数运行成功返回0,否则返回-1。

 

二、socket编程的其他函数说明

1网络字节顺序及其转换函数

1网络字节顺序

         每一台机器内部对变量的字节存储顺序不同,而网络传输的数据是一定要统一顺序的。所以对内部字节表示顺序与网络字节顺序不同的机器,一定要对数据进行转换,从程序的可移植性要求来讲,就算本机的内部字节表示顺序与网络字节顺序相同也应该在传输数据以前先调用数据转换函数,以便程序移植到其它机器上后能正确执行。真正转换还是不转换是由系统函数自己来决定的。

2有关的转换函数

unsigned short int htons(unsigned short int hostshort):主机字节顺序转换成网络字节顺序,对无符号短型进行操作4bytes

unsigned long int htonl(unsigned long int hostlong):主机字节顺序转换成网络字节顺序,对无符号长型进行操作8bytes

unsigned short int ntohs(unsigned short int netshort):网络字节顺序转换成主机字节顺序,对无符号短型进行操作4bytes

unsigned long int ntohl(unsigned long int netlong):网络字节顺序转换成主机字节顺序,对无符号长型进行操作8bytes

注:以上函数原型定义在netinet/in.h里


2IP地址转换

        有三个函数将数字点形式表示的字符串IP地址与32位网络字节顺序的二进制形式的IP地址进行转换

(1)unsigned long int inet_addr(constchar * cp):该函数把一个用数字和点表示的IP地址的字符串转换成一个无符号长整型,如:struct sockaddr_in ina

ina.sin_addr.s_addr=inet_addr("202.206.17.101")

该函数成功时:返回转换结果;失败时返回常量INADDR_NONE,该常量=-1,二进制的无符号整数-1相当于255.255.255.255,这是一个广播地址,所以在程序中调用iner_addr()时,一定要人为地对调用失败进行处理。由于该函数不能处理广播地址,所以在程序中应该使用函数inet_aton()。

(2)int inet_aton(const char * cp,struct in_addr *inp):此函数将字符串形式的IP地址转换成二进制形式的IP地址;成功时返回1,否则返回0,转换后的IP地址存储在参数inp中。

(3)char * inet_ntoa(struct in-addr in):将32位二进制形式的IP地址转换为数字点形式的IP地址,结果在函数返回值中返回,返回的是一个指向字符串的指针。

3、字节处理函数

        Socket地址是多字节数据,不是以空字符结尾的,这和C语言中的字符串是不同的。Linux提供了两组函数来处理多字节数据,一组以b(byte)开头,是和BSD系统兼容的函数,另一组以mem(内存)开头,是ANSI C提供的函数。

以b开头的函数有:

(1)void bzero(void * s,int n):将参数s指定的内存的前n个字节设置为0,通常它用来将套接字地址清0。

(2)void bcopy(const void * src,void * dest,int n):从参数src指定的内存区域拷贝指定数目的字节内容到参数dest指定的内存区域。

(3)int bcmp(const void * s1,const void * s2,int n):比较参数s1指定的内存区域和参数s2指定的内存区域的前n个字节内容,如果相同则返回0,否则返回非0。

注:以上函数的原型定义在strings.h中。

以mem开头的函数有:

(1)void * memset(void * s,int c,size_t n):将参数s指定的内存区域的前n个字节设置为参数c的内容。

(2)void * memcpy(void * dest,const void * src,size_t n):功能同bcopy(),区别:函数bcopy()能处理参数src和参数dest所指定的区域有重叠的情况,memcpy()则不能。

(4)int memcmp(const void * s1,const void * s2,size_t n):比较参数s1和参数s2指定区域的前n个字节内容,如果相同则返回0,否则返回非0。

注:以上函数的原型定义在string.h中。

 

三、程序说明

        本使用tcp协议进行通信,服务端进行监听,在收到客户端的连接后,发送数据给客户端;客户端在接受到数据后打印出来,然后关闭。

服务端:socket -- bind -- listen -- accept -- read/write -- close

客户端:socket -- connect -- read/write -- close

/*************************************************************************> File Name: client.c> Author: libang> Mail: 1838039453@qq.com > Created Time: 2014年04月03日 星期日 02时59分37秒************************************************************************/#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <sys/socket.h>
#include <resolv.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <unistd.h>
#include <arpa/inet.h>#define MAXBUF 1024int main(int argc,char *argv[])
{pid_t pid;int socket_fd,len;struct sockaddr_in dest;char buffer[MAXBUF];if(argc != 3){printf("error format,it must be:\n\t\t%s IP port\n",argv[0]);exit(EXIT_FAILURE);}if((socket_fd = socket(AF_INET,SOCK_STREAM,0)) < 0){perror("socket");exit(EXIT_FAILURE);}printf("Socket created!\n");bzero(&dest,sizeof(dest));dest.sin_family = AF_INET;dest.sin_port = htons(atoi(argv[2]));if(inet_aton(argv[1],(struct in_addr *)&dest.sin_addr.s_addr) == 0){perror(argv[1]);exit(errno);}if(connect(socket_fd,(struct sockaddr *)&dest,sizeof(dest)) == -1){perror("connect");exit(errno);}printf("Server connected!\n");if(-1 == (pid = fork())){perror("fork");exit(EXIT_FAILURE);}else if(pid == 0){while(1){bzero(buffer,MAXBUF);len = recv(socket_fd,buffer,MAXBUF,0);if(len > 0){printf("recv successful:'%s',%d byte recv\n",buffer,len);}else if(len < 0){perror("recv");break;}else{printf("the other one close,quit\n");break;}}}else{while(1){bzero(buffer,MAXBUF);//printf("please send message to send:");fgets(buffer,MAXBUF,stdin);if(!strncasecmp(buffer,"quit",4)){printf("I will quit!\n");break;}len = send(socket_fd,buffer,strlen(buffer) - 1,0);if(len < 0){perror("send");break;}}}close(socket_fd);return 0;
}
/*************************************************************************> File Name: server.c> Author: libang> Mail: 1838039453@qq.com > Created Time: 2016年04月03日 星期日 20时57分48秒************************************************************************/#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <sys/socket.h>
#include <resolv.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>#define MAXBUF 1024int main(int argc,char *argv[])
{int socket_fd,new_fd;socklen_t len;struct sockaddr_in my_addr,their_addr;pid_t pid;unsigned int myport,list_num;char buf[MAXBUF];if(argv[2]){myport = atoi(argv[2]);}elsemyport = 7575;if(argv[3]){list_num = atoi(argv[3]);}elselist_num = 10;if((socket_fd = socket(AF_INET,SOCK_STREAM,0)) == -1){perror("socket");exit(EXIT_FAILURE);}bzero(&my_addr,sizeof(my_addr));my_addr.sin_family = AF_INET;my_addr.sin_port = htons(myport);if(argv[1]){my_addr.sin_addr.s_addr = inet_addr(argv[1]);}elsemy_addr.sin_addr.s_addr = INADDR_ANY;len = sizeof(struct sockaddr);if(bind(socket_fd,(struct sockaddr *)&my_addr,len) == -1){perror("bind");exit(EXIT_FAILURE);}if(listen(socket_fd,list_num) == -1){perror("listen");exit(EXIT_FAILURE);}printf("wait for connect!\n");if((new_fd = accept(socket_fd,(struct sockaddr *)&their_addr,&len)) == -1){perror("accept");exit(EXIT_FAILURE);}elseprintf("server:got connection from %s,port %d,socket %d\n",inet_ntoa(their_addr.sin_addr),ntohs(their_addr.sin_port),new_fd);if(-1 == (pid = fork())){perror("fork");exit(EXIT_FAILURE);}else if(pid == 0){while(1){bzero(buf,MAXBUF);//printf("input the message to send:");fgets(buf,MAXBUF,stdin);if(!strncasecmp(buf,"quit",4)){printf("I will close the connect!\n");break;}len = send(new_fd,buf,strlen(buf) - 1,0);if(len < 0){printf("message '%s' send failure!error code is %d error message is '%s'\n",buf,errno,strerror(errno));break;}}}else{while(1){bzero(buf,MAXBUF);len = recv(new_fd,buf,MAXBUF,0);if(len > 0){printf("message recv successful!:'%s',%dByte recv\n",buf,len);}else if(len < 0){printf("recv failure!errno code is %d,errno message is ‘%s\n",errno,strerror(errno));break;}else{printf("the other one close quit!\n");break;}}}close(new_fd);close(socket_fd);return 0;
}
gcc -o server server.c

gcc -o client client.c 

./server 192.168.207.129 7575 5
./client 192.168.207.129 7575

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/466683.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

机器学习在本体中的应用研究文献综述

机器学习在本体标注中的应用研究文献综述<?xml:namespace prefix o ns "urn:schemas-microsoft-com:office:office" />本设计是基于语义搜索引擎展开研究&#xff0c;针对这个新兴的搜索引擎概念的提出&#xff0c;我们搜集了大量的资料并对此进行了一定的研…

20180209-shutil模块

下面讲解shutil模块的相关操作: 1.shutil.copyfileobj(fsrc, fdst, length16*1024) 将fsrc文件内容拷贝到fdst文件中&#xff0c;length是指一次拷贝多少个字节 源码&#xff1a;def copyfileobj(fsrc, fdst, length16*1024):"""copy data from file-like objec…

Pandas使用小技巧

1.获取存在缺失值的行或列 在进行缺失值筛选时&#xff0c;可以对缺失严重的行和列进行删除&#xff0c;首先进行缺失值的确定。 (1)缺失值的列和每列的缺失情况 #对每列的缺失值进行统计&#xff0c;并逆序排列 data.isnull.sum().sort_values(ascendingFalse) (2)缺失值的…

Linux C高级编程——网络编程之包裹函数

Linux网络编程&#xff08;六&#xff09;——包裹函数 宗旨&#xff1a;技术的学习是有限的&#xff0c;分享的精神是无限的。 系统调用不能保证每次都成功&#xff0c;必须进行出错处理。包裹函数就是把一般函数加了出错处理。包裹函数首字母大写。 /***********************…

输入一个数3256,将他从小到大输出,就是2356

这是知乎上面的一个题目&#xff0c;挺有意思&#xff0c;面试的时候应该是作为基础题&#xff0c;很多人不屑于看这样的题目&#xff0c;但是到自己些的时候&#xff0c;就会有很多问题。题目要求输入一个数3256&#xff0c;将他从小到大输出&#xff0c;就是2356分析输入的是…

在过渡到Agile中的十种错误

原文: http://www.ddj.com/architect/193402902为了走得更快必须减缓转变。从传统开发方法论到Agile的过渡中最普遍的10种错误&#xff1a;1直接全部参与。没有以试验项目作为开始。这样造成在项目推行新的方法论有很高风险&#xff0c;因为你在时间紧迫或风险较大的项目中没有…

深度学习之负荷分解——LSTM(一对多)任务场景

1.任务场景 以家庭为例&#xff0c;假设该家庭有m种电器和总负荷的曲线&#xff0c;其中&#xff0c;总负荷为,各个电器的负荷有&#xff08;m是电器个数&#xff0c;n是n个时刻&#xff09;。我们需要通过对总负荷曲线进行分解&#xff0c;识别出该负荷有几种电器同时运行实现…

这是我见过最秀的代码

这么秀的代码&#xff0c;你能写出来吗&#xff1f;技术主管来了都不好使&#xff0c;main函数里第一个函数必须是这个。佛祖保佑版&#xff1a;void godBless(void) { // _ooOoo_ // o8888888o // …

java-构建jar带哟参数提示的

使用command的cli包构建带有参数提示的jar包 需要引入command cli的依赖 <commons.version>1.2</commons.version> <dependency><groupId>commons-cli</groupId><artifactId>commons-cli</artifactId><version>${commons.vers…

Cortex M3存储器映射

CortexM3存储器系统 宗旨&#xff1a;技术的学习是有限的&#xff0c;分享的精神是无限的。 CM3 只有一个单一固定的存储器映射。这一点极大地方便了软件在各种 CM3 单片机间的移植。 存储空间的一些位置用于调试组件等私有外设&#xff0c;这个地址段被称为“私有外设区”。私…

sql server 分页

分页方案一&#xff1a;(利用Not In和SELECT TOP分页) 语句形式&#xff1a; SELECT TOP 10 * FROM TestTable WHERE (ID NOT IN (SELECT TOP 20 id FROM TestTable ORDER BY id)) ORDER BY ID SELECT TOP 页大小 * FROM TestTable WHERE (ID NOT IN (SELECT TOP 页大小*页数 i…

这些年,NLP常见的预训练模型剖析

“预训练-微调”&#xff08;pre-training and fine-tune&#xff09; 已经成为解决NLP任务的一种新的范式。基于预训练语言模型的词表示由于可以建模上下文信息&#xff0c;进而解决传统静态词向量不能建模“一词多义”语言现象的问题。传统的词向量有one-hot&#xff08;杜热…

Linux Ftrace 使用

Ftrace相关的文章如何利用ftrace精确跟踪特定进程调度信息1、Ftrace 是什么东西&#xff1f;Ftrace是一个直接内置在Linux内核中的跟踪工具。许多发行版在最近的发行版中已经启用了各种各样的Ftrace配置。Ftrace给Linux带来的好处之一是能够看到内核中发生了什么。因此&#xf…

java中原始数据文件的输入

in.data中的数据"28.7812 34.4632 31.3381 31.2834..."File fileInnew File("in.data");//File fileOutnew File("out.data");if(fileIn.exists()){System.out.println("the files path:"fileIn.getPath());System.out.println("…

Cortex M3寄存器组

寄存器组 宗旨&#xff1a;技术的学习是有限的&#xff0c;分享的精神是无限的。 1、通用目的寄存器R0~R7 R0-R7 也被称为低组寄存器。所有指令都能访问它们。它们的字长全是 32 位&#xff0c;复位后的初始值是不可预料的。 2、通用目的寄存器 R8-R12 R8-R12 也被称为高组寄…

深度学习-超参数调优

在机器学习中有很多调优的方式机器学习——超参数调优&#xff0c;深度学习中也存在同样的方式&#xff0c;接下来&#xff0c;介绍一下深度学习框架里边的自动调参模块。 1. 基于Tensorflow的Keras tuner 官方教程如下&#xff1a;Introduction to the Keras Tuner | Tens…

【文章汇总】嵌入式Linux公众号

据悉,深圳某工程师沦为C语言笔试枪手 修改cmdline 把内存改成512MB 上拉电阻的作用

Leetcode分类

二叉树平衡二叉树easy 108. Convert Sorted Array to Binary Search Tree 2. 二叉树 617. Merge Two Binary Trees 104. Maximum Depth of Binary Tree 列表题&#xff1a;21. Merge Two Sorted Lists 字符串题数组题排序347. Top K Frequent Elements 归并递归70. Climbing S…

第5节 三个败家子(5)——刘封,被封印的秘密

根据《三国志刘封传》记载“刘封者&#xff0c;本罗侯寇氏之子&#xff0c;长沙刘氏之甥也。先主至荆州&#xff0c;以未有继嗣&#xff0c;养封为子。及先主入蜀&#xff0c;自葭萌还攻刘璋&#xff0c;时封年二十余”。等等&#xff0c;各位看官说了&#xff0c;时间上不对啊…

Paddle——常见的评估指标

在模型评估过程中&#xff0c;分类、回归、排序问题往往使用不同的指标进行评估。分类问题通常用准确率、召回率、精准率、F1值等指标进行评估&#xff1b;回归问题使用MSE、RMSE、R^2、MAPE等&#xff1b; 1 分类评估原理 1.1 准确率的局限性 我们经常接触的评价指标就是准…