在linux下有下面结构:
sockaddr
struct sockaddr
{
sa_family_t sa_family; /*addressfamily,AF_xxx*/
char sa_data[14]; /*variable-length address,14 bytes of protocol address*/
}
sa_family是地址家族,一般都是“AF_xxx”的形式。通常大多用的是都是AF_INET,代表TCP/IP协议族。
sa_data是14字节协议地址。
此数据结构用做bind、connect、recvfrom、sendto等函数的参数,指明地址信息。但一般编程中并不直接针对此数据结构操作,而是使用另一个与sockaddr等价的数据结构.
sockaddr_in(在netinet/in.h中定义)
struct sockaddr_in
{
sa_family_t sin_family;
/*Address family,一般来说AF_INET(地址族)PF_INET(协议族)*/
in_port_t sin_port;
/*Port number(必须要采用网络数据格式,普通数字可以用htons()函数转换成网络数据格式的数字)*/
struct in_addr sin_addr;
/*IPv4 address*/
unsigned char sin_zero[8];
/*没有实际意义,只是为了跟sockaddr结构在内存中对齐*/
};
in_addr结构, (在<arpa/inet.h>中定义)
typedef struct in_addr
{
in_addr_t s_addr;
};
struct sockaddr是通用的套接字地址,而struct sockaddr_in则是internet环境下套接字的地址形式,二者长度一样,
都是16个字节。二者是并列结构,指向sockaddr_in结构的指针也可以指向sockaddr。一般情况下,需要把sockaddr_in
结构强制转换成sockaddr结构再传入系统调用函数中。
结构体in_addr 用来表示一个32位的IPv4地址.in_addr_t 一般为 32位的unsigned int,其字节顺序为网络顺序(network byte ordered),即该无符号整数采用大端字节序,其中每8位代表一个IP地址位中的一个数值.例如192.168.3.144记为0xc0a80390,其中 c0 为192 ,a8 为 168, 03 为 3 , 90 为 144打印的时候可以调用inet_ntoa()函数将其转换为char *类型.
sin_family指代协议族,在socket编程中只能是AF_INET
sin_port存储端口号(使用网络字节顺序),在linux下,端口号的范围0~65535,同时0~1024范围的端口号已经被系统使用或保留。
sin_addr存储IP地址,使用in_addr这个数据结构
sin_zero是为了让sockaddr与sockaddr_in两个数据结构保持大小相同而保留的空字节。可以用bzero()或memset()函数将其置为零。
s_addr按照网络字节顺序存储IP地址。
使用时,先用sockaddr_in建立所需要的信息,然后用memset函数初始化就可以了
sockaddr_in的初始化
sockaddr_in mysock;
memset((char*)&mysock,0,sizeof(mysock));
mysock.sin_family=AF_INET;
mysock.sin_port=htons(1234);//1234是端口号
mysock.sin_addr.s_addr=inet_addr("192.168.0.1");
服务端
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h> //inet_addr();
#include <arpa/inet.h>
#include <errno.h>
extern int errno;
int main()
{
<span style="white-space:pre"> </span>int fd = socket(AF_INET, SOCK_STREAM, 0);
<span style="white-space:pre"> </span>printf("socket id = %d\n", fd);
<span style="white-space:pre"> </span>struct sockaddr_in servaddr;
<span style="white-space:pre"> </span>servaddr.sin_family = AF_INET;
<span style="white-space:pre"> </span>servaddr.sin_port = htons(11111);
<span style="white-space:pre"> </span>servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
<span style="white-space:pre"> </span>int ret = bind(fd, (struct sockaddr*)&servaddr, sizeof(servaddr));
<span style="white-space:pre"> </span>if(ret < 0)
<span style="white-space:pre"> </span>{
<span style="white-space:pre"> </span>fprintf(stderr, "error:%d\n", strerror(errno));
<span style="white-space:pre"> </span>close(fd);
<span style="white-space:pre"> </span>return -1;
<span style="white-space:pre"> </span>}
<span style="white-space:pre"> </span>listen(fd, 5);
<span style="white-space:pre"> </span>struct sockaddr_in peer; //保存对方的地址信息
<span style="white-space:pre"> </span>socklen_t size;
<span style="white-space:pre"> </span>size = sizeof(peer);
<span style="white-space:pre"> </span>int newfd = accept(fd, (struct sockaddr*)&peer, &size);
<span style="white-space:pre"> </span>printf("ip: %s, port: %d\n", inet_ntoa(peer.sin_addr), ntohs(peer.sin_port));
<span style="white-space:pre"> </span>char buff[100];
<span style="white-space:pre"> </span>//fgets(buff, 100. stdin);
<span style="white-space:pre"> </span>//write(newfd, buff, strlen(buff));
<span style="white-space:pre"> </span>int cnt = read(newfd, buff, 100);
<span style="white-space:pre"> </span>write(STDOUT_FILENO, buff, cnt);
<span style="white-space:pre"> </span>close(newfd);
<span style="white-space:pre"> </span>return 0;
}
客户端
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h> //inet_addr();
#include <arpa/inet.h>
#include <errno.h>
extern int errno;
int main()
{
<span style="white-space:pre"> </span>int fd = socket(AF_INET, SOCK_STREAM, 0);
<span style="white-space:pre"> </span>printf("socket id = %d\n", fd);
<span style="white-space:pre"> </span>struct sockaddr_in servaddr;
<span style="white-space:pre"> </span>servaddr.sin_family = AF_INET;
<span style="white-space:pre"> </span>servaddr.sin_port = htons(11111);
<span style="white-space:pre"> </span>servaddr.sin_addr.s_addr = inet_addr("127.0.0.1");
<span style="white-space:pre"> </span>connect(fd, (struct sockaddr *)&servaddr, sizeof(servaddr));
<span style="white-space:pre"> </span>int buff[100];
<span style="white-space:pre"> </span>fgets(buff, 100, stdin);
<span style="white-space:pre"> </span>write(fd, buff, strlen(buff));
<span style="white-space:pre"> </span>close(fd);
<span style="white-space:pre"> </span>return 0;<span style="white-space:pre"> </span>
}