@rfish
2015-09-10T03:08:51.000000Z
字数 2829
阅读 2010
培训
用文件描述符创建套接字。
类型 | 特点 | 说明 |
---|---|---|
流式socket | TCP | |
数据包socket | UDP |
只能转换ipv4
typedef uint32_t in_addr_t;
struct in_addr {
in_addr_t s_addr;
};
//----------inet_aton
int inet_aton(const char *cp/*点分ip*/
, struct in_addr *inp /*存放转换后的二进制地址*/
);
//----------inet_addr
in_addr_t inet_addr(const char *cp);/*传入需要转换的点分ip*/
//先声明in_addr结构体,然后取其中的s_addr来保存返回值。
char *inet_ntoa(struct in_addr in);
传入保存二进制地址的结构体,返回点分字符串。
都是二进制转点分式。但是:
ntoa类函数
只能转换32位的ipv4地址
ntop类函数
能转换ipv4和ipv6地址
short ,16位
大端
ip的高位存储在内存的低位
小端
ip的高位存储在内存的高位
转换函数:
#include <arpa/inet.h>
uint32_t htonl(uint32_t hostlong);
uint16_t htons(uint16_t hostshort);
uint32_t ntohl(uint32_t netlong);
uint16_t ntohs(uint16_t netshort);
程序函数转化后就是大端序列。有端口号就必须用大端。
注意:
在使用时,由于cup的不一样,有的是大端,有的是小端,所有为了代码的移植性,均转换为网络序使用
Address already in usr
解决:
可以用netstat -anp | more 可以看到客户端还保持着与服务器的连接(还在使用服务器bind的端口)。这是由于client没有执行close,连接还会等待client的FIN包一段时间。解决方法是使用setsockopt
,使得socket可以被重用,是最常用的服务器编程要点。具体的做法为是,在socket调用和bind调用之间加上一段对socket的设置:Address already in use的解决方法
解决:
每次使用前将buff清零,不然打印出来可能会有乱码。因为没有\0
#include <sys/types.h>
#include <sys/socket.h>
ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,struct sockaddr *src_addr, socklen_t *addrlen);
ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,const struct sockaddr *dest_addr, socklen_t addrlen);
udp协议实现,将数据发送本网段的广播地址。
本机宏定义IP地址
INADDR_ANY
是用于多IP机器上
比如你的机器有三个ip
192.168.1.1
202.202.202.202
61.1.2.3
如果你serv.sin_addr.s_addr=inet_addr("192.168.1.1");
然后监听100端口
这时其他机器只有connect 192.168.1.1:100才能成功。
connect 202.202.202.202:100和connect 61.1.2.3:100都会失败。
如果serv.sin_addr.s_addr=htonl(INADDR_ANY);
的话,无论连接哪个ip都可以连上的。
int on =1;
setsockopt(sockfd,SOL_SOCKET,SO_BROADCAST, )
用D类地址描述组播编号
例如:230.1.1.1
默认组播打开的
加入组播地址。
struct ip_mreq{
struct in_addr imr_multiaddr;
struct in_addr imr_interface;
};//该结构体库文件已经声明过,可以直接用
struct ip_mreq mreq;
bzero(&mreq,sizeof(mreq));
mreq.imr_multiaddr.s_addr=inet_addr("组播地址");
mreq.imr_interface.s_addr=htol(INADDR_ANY);
/*
inet_pton(AF_INET,"192.168.7.89",(void*)&mreq.imr_interface);//本条和上一条代码效果相同,二选一
*/
setsockopt(sockfd,IPPROTO_IP,IP_ADD_MEMBERSHIP,&mreq,sizeof(mreq));
注意:
在数据链路层中的目标mac地址为:
mac总共:48bit/6byte
24位 1位 23位 0x01005E
0
组播ip地址低23位
也就是只匹配了组播地址的低23位,到网络层,会再次匹配组播地址。