字节序概念:是指多字节数据的存储顺序
分类:
大端格式:将低位字节数据存储在低地址
小端格式:将高位字节数据存储在低地址
注意:
LSB:低地址
MSB:高地址

如何判断当前系统的字节序:
#include <stdio.h>
union un
{
int a;
char b;
}
int main()
{
union un myun;
myun.a = 0x12345678;
printf("a = %#x\n",myun.a);
printf("b = %#x\n",myun.b);
if(myun.b == 0x78){
printf("小端存储\n");
}
else{
printf("大端存储\n");
}
return 0;
}
结果展示:

在需要字节序转换的时候一般调用特定字节序转换函数
host --> network
1 -- htonl
#include<arpa/inet.h>
uint32_t htonl(uint32_t hostint32);
功能:
将32位主机字节序数据转换成网络字节序数据
参数:
hostint32: 待转换的32位主机字节序数据
返回值:
成功:返回网络字节序的值
2 -- htons
#include<arpa/inet.h>
uint16_t htons(uint16_t hostint16);
功能:
将16位主机字节序数据转换成网络字节序数据
参数:
hostint16: 待转换的16位主机字节序数据
返回值:
成功:返回网络字节序的值
network --> host
3 -- ntohl
#include<arpa/inet.h>
uint32_t ntohl(uint32_t netint32);
功能:
将32位网络字节序数据转换成主机字节序数据
参数:
netint32: 待转换的32位网络字节序数据
返回值:
成功:返回主机字节序数据
4 -- ntohs
#include<arpa/inet.h>
uint16_t ntohs(uint16_t netint16);
功能:
将16位网络字节序数据转换成主机字节序数据
参数:
netint16: 待转换的16位网络字节序数据
返回值:
成功:返回主机字节序数据
案例:
#include <stdio.h>
#include <arpa/inet.h>
int main()
{
int a = 0x12345678;
short a = 0x1234;
printf("%#x\n",htonl(a));
printf("%#x\n",htons(b));
return 0;
}
人为识别的ip地址是点分十进制的字符串形式,但是计算机或网络中识别的ip地址是整型数据,所以需要转化
#include <arpa/inet.h>
int inet_pton(int family,const char *strptr,void *addrptr);
功能:
将点分十进制数串转换成32位无符号整数
参数:
family 协议族
AF_INET ipv4网络协议
AF_INET6 iPV6网络协议
strptr 点分十进制数串
addrptr 32位无符号整数的地址
返回值:
成功返回1、失败返回其他
案例:
#include <stdio.h>
#include <arpa/inet.h>
int main()
{
char ip_str[] = "198.168.3.103";
unsigned int ip_int = 0;
unsigned char *ip_p = NULL;
//将点分十进制ip地址转化为32位无符号整形数据
inet_pton(AF_INET,ip_str,&ip_int);
printf("ip_int = %d\n",ip_int;
ip_p = (char *)&ip_int;
printf("in_uint = %d,%d,%d,%d\n",*ip_p,*(ip_p+1),*(ip_p+2),*(ip_p+3));
return 0;
}
#include <arpa/inet.h>
const char * inet_ntop(int family,const void *addrptr,char *strptr, size_t len);
功能:
将32位无符号整数转换成点分十进制数串的ip地址
参数:
family 协议族
AF_INET ipv4网络协议
AF_INET6 iPV6网络协议
addrptr 32位无符号整数的地址
strptr 点分十进制数串
len strptr缓存区长度
len的宏定义
#define INET_ADDRSTRLEN 16 //for ipv4
#define INET6_ADDRSTRLEN 46 //for ipv6
返回值:
成功返回1、失败返回其他
案例:
#include <stdio.h>
#include <arpa/inet.h>
int main()
{
unsigned char ip_int[] = {198,168,3,103};
char ip_str[16] = ""; //"198.168.3.103"刚好16个字节
inet_ntop(AF_INET,&ip_int,ip_str,16);
printf("ip_s = %s\n",ip_str);
return 0;
}
这两个函数只能用在ipv4地址的转换
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>
in_addr_t inet_addr(const char *cp);
功能:
将点分十进制ip地址转化为整型数据
参数:
cp:点分十进制的ip地址
返回值:
成功:整型数据
char *inet_ntoa(struct in_addr in);
功能:将整型数据转化位点分十进制的ip地址
参数:
in: 保存ip地址的结构体
返回值:
成功:点分十进制的ip地址
UDP协议
面向无连接的用户数据报协议,在传输数据前不需要先建立连接;目的主机的运输层收到UDP报文后,不需要给出任何确认。
UDP特点
UDP应用
DNS(域名解析)、NFS(网络文件系统)、RTP(流媒体)等
一般语音和视频童话都是使用UDP通信的。
Socket作用:提供不同主机上的进程之间的通信;
Socket特点:
socket分类:
SOCK_STREAM, 流式套接字,用于TCP;
SOCK_DGRAM, 数据报套接字,用于UDP;
SOCK_RAW, 原始套接字,对于其他层次的协议操作时需要使用这个类型
UDP网络编程流程:
服务器:
创建套接字socket();
将服务器的ip地址、端口号与套接字进行绑定;
接收数据recvfrom()
发送数据sendto()
客户端:
创建套接字socket()
发送数据sendto()
接收数据recvfrom()
关闭套接字close()
#include<sys/types.h>
#include<sys/socket.h>
int socket(int domain, int type, int protocol);
功能:
创建一个套接字,返回一个文件描述符;
参数:
domain:通信域,协议族;
AF_UNIX 本地通信
AF_INET ipv4网络协议
AF_INET6 ipv6网络协议
AF_PACKET 底层接口
type: 套接字的类型
SOCKET_STREAM 流式套接字(TCP)
SOCKET_DGRAM 数据报套接字(UDP)
SOCKET_RAW 原始套接字(用于链路层)
特点:
创建套接字时,系统不会分配端口
创建的套接字默认属性是主动的,即主动发起服务的请求,当作为服务器时,往往需要修改为被动的。
#include <stdio.h>
#include <sys/socket.h>
#include <sys/types>
int main(int argc, char const *argv[]){
//使用socket函数创建套接字
//创建一个用于UDP网络编程的套接字
int sockfd = 0;
sockfd = socket(AF_INET,SOCKE_DGRAM,0);
if(sockfd < 0){
perror("socket");
exit(-1);
}
printf("sockfd = %d\n",sockfd);//任何一个进程在开启或创建的时候会分配三个文件描述符(0,1,2)
}
在网络编程中经常使用的结构体
#include <netinet/in.h>
struct in_addr
{
in_addr_t s_addr; // 4字节
}
struct sockaddr_in
{
sa_family_t sinfamily; //2字节;
in_port_t sin_port; //2字节;
struct in_addr sin_addr; //4字节;
char sin_zero[8] //8字节
}
为了使不同格式地址能被传入套接字函数,地址须要强制转换成通用套接字地址结构,原因是因为不同场合所使用的结构体不一样,但是调用的函数却是同一个,所以定义一个通用结构体,当在指定场合使用时,在根据要求传入指定的结构体即可。
通用结构体sockaddr
头文件#include <netinet/in.h>
struct sockaddr
{
sa_family_t sa_family; //2字节
char sa_data[14] //14字节
}
//注意,以上3个结构在Linux系统中已经定义
在定义源地址和目的地址结构的时候,选用struct sockaddr_in;
例:
struct sockaddr_in my_addr;
当调用编程接口函数,且该函数需要从传入地址结构时需要用struct sockaddr进行强制转换
例:
bind(sockfd,(struct sockaddr*)&my_addr,sizeof(my_addr));
ssize_t sendto(int sockfd,const void *buf,size_t nbytes,int flags,const struct sockaddr *to, socklen_t addrlen);
功能:
向to结构体指针中指定的ip,发送UDP数据
参数:
sockfd: 套接字
buf: 发送数据缓存区
nbytes: 发送数据缓存区的大小
flags: 一般为0
to: 指向目的主机地址结构体的指针
addrlen: to指向内容的长度
注意:
通过to和addrlen确定目的地址
可以发送0长度的UDP数据包
返回值:
成功:发送数据的字符数
失败:-1
设置网络调试助手(在windows下运行的软件)中的属性
注意:ip地址不能随意设置,必须是当前windows的ip地址
ubuntu下客户段的代码编写:
#include <stdio.h> //printf
#include <stdlib.h> //exit
#include <sys/types.h>
#include <sys/socket.h> //socket
#include <netinet/in.h> //sockaddr_in
#include <arpa/inet.h> //htons inet_addr
#include <unisted.h> //close
#include <string.h>
int main()
{
int sockfd;
if((sockfd = socket(AF_INET,SOCK_DGRAM,0)) == -1)
{
perrpr("fail to socket");
exit(1);
}
printf("sockfd = %d",sockfd);
//第二步:填充服务器网络信息结构体 sockaddr_in(一般不需要,系统会自动分配)
struct sockaddr_in severaddr;
serveraddr.sin_family = AF_INET; //协议族 AF_INET:ipv4网络协议
serveraddr.sin_addr.s_addr = inet_addr("192.168.3.78"); //ip地址
serveraddr.sin_port = htons(8080);
socklen_t addrlen = sizeof(serveraddr)
//第三步:发送数据
char buf[128] = "";
while(1)
{
fgets(buf,128,stdin);
buf[strlen(buf) - 1] = '\0'; //把buf字符串中的\n转化为\0
if(sendto(sockfd,buf,N,0,(struct sockaddr *)&serveraddr,addrlen));
{
perror("fail to sendto");
exit(1);
}
}
//第四步:关闭套接字文件描述符
close(socketfd);
return 0;
}
UDP网络程序想要收取数据需要什么条件?
确定的ip地址
确定的port
怎么完成上面的条件呢?
接收端:使用bind函数,来完成地址结构与socket套接字的绑定,这样ip、port就固定了;
发送端:在sendto函数中指定接收端的ip、port,就可以发送数据了。
由于服务器是被动的,客户端是主动的,所以一般先运行服务器,后运行客户端,所以服务器需要固定自己的信息(ip地址和端口号),这样客户端才可以找到服务器并与之通信,但是客户端一般不需要bind绑定,因为系统会自动给客户端分配ip地址和端口号。
int bind(int sockfd,const struct sockaddr *myaddr,socklen_t addrlen);
功能:
将本地协议地址与sockfd绑定
参数:
sockfd: 文件描述符,socket的返回值
addr: 网络信息结构体
通用结构体(一般不用)
struct sockaddr
网络信息结构体 sockaddr_in
#include<netinet/in.h>
struct sockaddr_in
addrlen: addr的长度
返回值:
成功:0
失败:-1
示例:
#include <stdio.h> //printf
#include <stdlib.h> //exit
#include <sys/types.h>
#include <sys/socket.h> //socket
#include <netinet/in.h> //sockaddr_in
#include <arpa/inet.h> //htons inet_addr
#include <unisted.h> //close
#include <string.h>
int main(int argc, char **argv)
{
if(argc < 3){
fprintf(stderr,"Useage: %s ip port\n",argv[0]);
exit(1);
}
//第一步:创建套接字
int sockfd;
if((sockfd = socket(AF_INET,SOCK_DGRAM,0))== -1)
{
perror("fail to socket");
exit(1);
}
//第二步:将服务器的网络信息结构绑定前进行填充
struct sockaddr_in serveraddr;
serveraddr.sin_family = AF_INET;
serveraddr.sin_addr.s_addr = inet_addr(agrv[1]);
serveraddr.sinport = htons(atoi(argv[2]));
//第三步:将网络信息结构体与套接字绑定
if(bind(sockfd,(struct sockaddr*)&serveraddr,sizeof(serveraddr))==-1){
perror("fail to bind");
exit(1);
}
return 0;
}
ssize_t recvfrom(int sockfd,void *buf,size_t nbytes,int flags, struct sockaddr *from,socklen_t *addrlen);
功能:
接收UDP数据,并将源地址信息保存在from指向的结构中
参数:
sockfd: 套接字
buf: 接收数据缓冲区
nbytes: 接收数据缓冲区的大小
flags: 套接字标志(常为0)
0 阻塞
MSG_DONTWAIT 非阻塞
from: 源地址结构体指针,用来保存数据的来源
addrlen: from所指内容的长度
注意:
通过from和addrlen参数存放数据来源信息
from和addrlen可以为NULL,表示不保存数据来源
返回值:
成功:接收到的字符数
失败:-1
此时网络调试助手作为客户端,ubuntu的程序作为服务器
设置客户端(网络调试助手)

设置服务器(ubuntu程序)
#include <stdio.h> //printf
#include <stdlib.h> //exit
#include <sys/types.h>
#include <sys/socket.h> //socket
#include <netinet/in.h> //sockaddr_in
#include <arpa/inet.h> //htons inet_addr
#include <unisted.h> //close
#include <string.h>
int main(int argc, char **argv)
{
if(argc < 3){
fprintf(stderr,"Useage: %s ip port\n",argv[0]);
exit(1);
}
//第一步:创建套接字
int sockfd;
if((sockfd = socket(AF_INET,SOCK_DGRAM,0))== -1)
{
perror("fail to socket");
exit(1);
}
//第二步:将服务器的网络信息结构绑定前进行填充
struct sockaddr_in serveraddr;
serveraddr.sin_family = AF_INET;
serveraddr.sin_addr.s_addr = inet_addr(agrv[1]); //192.168.3.103
serveraddr.sinport = htons(atoi(argv[2])); //9999
//第三步:将网络信息结构体与套接字绑定
if(bind(sockfd,(struct sockaddr*)&serveraddr,sizeof(serveraddr))==-1){
perror("fail to bind");
exit(1);
}
//接收数据
char buf[128] = "";
struct sockaddr_in clientaddr;
socklen_t addrlen = sizeof(struct sockaddr_in);
while(1){
if(recvfrom(sockfd,128,0,(struct sockaddr *)&clientaddr,&addrlen) == -1){
perror("fail to recvfrom");
exit(1);
}
}
//打印数据
//打印客户端的ip地址和端口号
printf("ip:%s,port:%d\n",inet_ntoa(clientaddr.sin_addr),ntohs(clientaddr.sin_port));
//打印接收到数据
printf("from client:%s\n",buf);
return 0;
}
其中在网络编程开发中client和server双方既可以有发送数据还可以接收数据;一般认为提供服务的一方为server,而接受服务的另一方为client。
1.本地IP、本地端口(我是谁)
2.目的IP、目的端口(发给谁)
3.在客户端的代码中,我们只设置了目的IP、目的端口
客户端的本地ip、本地port是我们调用sendto的时候linux系统底层自动给客户端分配的;分配端口的方式为随机分配,即每次运行系统给的port不一样
//UDP客户端的实现
#include <stdio.h> //printf
#include <stdlib.h> //exit
#include <sys/types.h>
#include <sys/socket.h> //socket
#include <netinet/in.h> //sockaddr_in
#include <arpa/inet.h> //htons inet_addr
#include <unisted.h> //close
#include <string.h>
int main(int argc,char **argv)
{
if(argc < 3){
fprintf(stderr,"Usage: %s <ip> <port>\n",agrv[0]);
exit(1);
}
int sockfd; //文件描述符
struct sockaddr_in serveraddr; //服务器网络信息结构体
socklen_t addrlen = sizeof(serveraddr);
//第一步:创建套接字
if((sockfd = socket(AF_INET,SOCK_DGRAM,0)) < 0){
perror("fail to socket");
exit(1);
}
//客户端自己指定自己的ip地址和端口号,一般不需要,系统会自动分配
struct sockaddr_in clientaddr;
clientaddr.sin_family = AF_INET;
clientaddr.sin_addr.s_addr = inet_addr(argv[3]); //客户端的ip地址
clientaddr.sin_port = htons(atoi(argv[4])); //客户端的端口号
//第二步:填充服务器网络信息结构体
//inet_addr:将点分十进制字符串ip地址转换为整型数据
//htons:将主机字节序转化为网络字节序
//atoi:将数字型字符串转化为整型数据
serveraddr.sin_family = AF_INET;
serveraddr.sin_addr.s_addr = inet_addr(argv[1]);
serveraddr.sin_port = htons(atoi(argv[2]));
//第三步:进行通信
char buf[32] = "";
while(1){
fgets(buf,sizeof(buf),stdin);
buf[strlen(buf) - 1] = '\0';
if(sendto(sockfd,buf,sizeof(buf),(struct sockaddr *)&serveraddr,sizeof(serveraddr)))
{
perror("fail to sendto");
exit(1);
}
char text[32] = "";
if(recvfrom(sockfd,text,sizeof(text),0,(struct sockaddr *)&serveraddr,&addrlen) == -1){
perror("fail to recvfrom");
exit(1);
}
printf("from server:%s\n",text);
}
//第四步:关闭文件描述符
close(sockfd);
return 0;
}
1.服务器之所以要bind是因为它的本地port需要是固定的,而不是随机的
2.服务器也可以主动地给客户端发送数据
3.客户端也可以用bind,这样客户端的本地端口就是固定的了,但一般不这样做。
//UDP服务器的实现
#include <stdio.h> //printf
#include <stdlib.h> //exit
#include <sys/types.h>
#include <sys/socket.h> //socket
#include <netinet/in.h> //sockaddr_in
#include <arpa/inet.h> //htons inet_addr
#include <unisted.h> //close
#include <string.h>
int main(int argc,char **argv)
{
if(argc < 3){
fprintf(stderr,"Usage: %s <ip> <port>\n",agrv[0]);
exit(1);
}
int sockfd; //文件描述符
struct sockaddr_in serveraddr; //服务器网络信息结构体
socklen_t addrlen = sizeof(serveraddr);
//第一步:创建套接字
if((sockfd = socket(AF_INET,SOCK_DGRAM,0)) < 0){
perror("fail to socket");
exit(1);
}
//第二步:填充服务器网络信息结构体
//inet_addr:将点分十进制字符串ip地址转换为整型数据
//htons:将主机字节序转化为网络字节序
//atoi:将数字型字符串转化为整型数据
serveraddr.sin_family = AF_INET;
serveraddr.sin_addr.s_addr = inet_addr(argv[1]);
serveraddr.sin_port = htons(atoi(argv[2]));
//第三步:将套接字与服务器网络信息结构体绑定
if(bind(sockfd,(struct sockaddr *)&serveraddr, addrlen) < 0){
perror("fail to bind");
exit(1);
}
while(1){
//第四步:进行通信
char text[32] = "";
struct sockaddr_in clientaddr;
if(recvfrom(sockfd,text,sizeof(text),0,(struct sockaddr *)&clientaddr,&addrlen) == -1){
perror("fail to recvfrom");
exit(1);
}
printf("[%s - %d]: %s\n",inet_ntoa(clientaddr.sin_addr),ntohs(clientaddr.sin_port),text);
strcat(text,"*_*");
if(sendto(sockfd,text,sizeof(text),0,(struct sockaddr *)&clientaddr,addrlen)){
perror("fail to sendto");
exit(1);
}
}
//第四步:关闭文件描述符
close(sockfd);
return 0;
}
执行结果:

几个月前,我读了一篇关于rubygem的博客文章,它可以通过阅读代码本身来确定编程语言。对于我的生活,我不记得博客或gem的名称。谷歌搜索“ruby编程语言猜测”及其变体也无济于事。有人碰巧知道相关gem的名称吗? 最佳答案 是这个吗:http://github.com/chrislo/sourceclassifier/tree/master 关于ruby-寻找通过阅读代码确定编程语言的rubygem?,我们在StackOverflow上找到一个类似的问题:
网络编程套接字网络编程基础知识理解源`IP`地址和目的`IP`地址理解源MAC地址和目的MAC地址认识端口号理解端口号和进程ID理解源端口号和目的端口号认识`TCP`协议认识`UDP`协议网络字节序socket编程接口`sockaddr``UDP`网络程序服务器端代码逻辑:需要用到的接口服务器端代码`udp`客户端代码逻辑`udp`客户端代码`TCP`网络程序服务器代码逻辑多个版本服务器单进程版本多进程版本多线程版本线程池版本服务器端代码客户端代码逻辑客户端代码TCP协议通讯流程TCP协议的客户端/服务器程序流程三次握手(建立连接)数据传输四次挥手(断开连接)TCP和UDP对比网络编程基础知识
我完全不是程序员,正在学习使用Ruby和Rails框架进行编程。我目前正在使用Ruby1.8.7和Rails3.0.3,但我想知道我是否应该升级到Ruby1.9,因为我真的没有任何升级的“遗留”成本。缺点是什么?我是否会遇到与普通gem的兼容性问题,或者甚至其他我不太了解甚至无法预料的问题? 最佳答案 你应该升级。不要坚持从1.8.7开始。如果您发现不支持1.9.2的gem,请避免使用它们(因为它们很可能不被维护)。如果您对gem是否兼容1.9.2有任何疑问,您可以在以下位置查看:http://www.railsplugins.or
我创建了一个由于“在运行时执行的单例元类定义”而无法编码的对象(这段代码的描述是否正确?)。这是通过以下代码执行的:#defineclassXthatmyusesingletonclassmetaprogrammingfeatures#throughcallofmethod:break_marshalling!classXdefbreak_marshalling!meta_class=class我该怎么做才能使对象编码正确?是否可以从对象instance_of_x的classX中“移除”单例组件?我真的需要一个建议,因为我们的一些对象需要通过Marshal.dump序列化机制进行缓存。
我正在查看Ruby日志记录库Logging.logger方法并从sourceatgithub提出问题与这段代码有关:logger=::Logging::Logger.new(name)logger.add_appendersappenderlogger.additive=falseclass我知道类 最佳答案 这实际上删除了方法(当它实际被执行时)。这是确保close不会被调用两次的保障措施。看起来好像有嵌套的“class 关于Ruby元编程问题,我们在StackOverflow上找到一
使用Paperclip,我想从这样的URL抓取图像:require'open-uri'user.photo=open(url)问题是我最后得到一个像“open-uri20110915-4852-1o7k5uw”这样的文件名。有什么方法可以更改user.photo上的文件名?作为一个额外的变化,Paperclip将我的文件存储在S3上,所以如果我可以在初始分配中设置我想要的文件名就更好了,这样图像就会上传到正确的S3key。像这样:user.photo=open(url),:filename=>URI.parse(url).path 最佳答案
我正在开发一个xcode自动构建系统。在执行一些预构建验证时,我想检查指定的证书文件是否已被撤销。我了解securityverify-cert验证其他证书属性但不验证吊销。我如何检查撤销?我正在用Ruby编写构建系统,但我对任何语言的想法都持开放态度。我阅读了这个答案(Openssl-Howtocheckifacertificateisrevokedornot),但指向底部的链接(DoesOpenSSLautomaticallyhandleCRLs(CertificateRevocationLists)now?)进入的Material对我的目的来说有点过于复杂(用户上传已撤销的证书是一
关闭。这个问题是off-topic.它目前不接受答案。想改进这个问题吗?Updatethequestion所以它是on-topic用于堆栈溢出。关闭11年前。Improvethisquestion我不经常使用ruby-通常它加起来相当于每两个月或更长时间编写一次脚本。我的大部分编程都是使用C++进行的,这与ruby有很大不同。由于我与ruby之间的差距如此之大,我总是忘记语言的基本方面(比如解析文本文件和其他简单的东西)。我想每天练习一些基本的东西,我想知道是否有一些我可以订阅的网站,并且会向我发送当天的Ruby问题或类似的东西。有人知道这样的站点/Internet服务吗?
我一直在寻找一种以编程方式或通过命令行将mp3转换为aac的方法,但没有成功。理想情况下,我有一段代码可以从我的Rails应用程序中调用,将mp3转换为aac。我安装了ffmpeg和libfaac,并能够使用以下命令创建aac文件:ffmpeg-itest.mp3-acodeclibfaac-ab163840dest.aac当我将输出文件的名称更改为dest.m4a时,它无法在iTunes中播放。谢谢! 最佳答案 FFmpeg提供AAC编码功能(如果您已编译它们)。如果您使用的是Windows,则可以从here获取完整的二进制文件。
我想输入一个字符串并返回一个可用于描述字符串结构的正则表达式。正则表达式将用于查找更多与第一个结构相同的字符串。这是故意模棱两可的,因为我肯定会漏掉SO社区中的某个人会发现的情况。请发布任何和所有可能的方法来做到这一点。 最佳答案 简单的答案(可能不是您想要的)是:返回输入字符串(正则表达式特殊字符转义)。这始终是与字符串匹配的正则表达式。如果您希望识别某些结构,则必须提供有关您希望识别的结构类型的更多信息。如果没有这些信息,问题就会以模棱两可的方式陈述,并且有许多可能的解决方案。例如,输入字符串'aba'可以描述为'阿巴''阿巴*