socket的地址数据结构根据不同的系统以及网络环境有不同形式。为了使不同格式地址能够被传入套接字函数,必须强制将地址结构转换为:
struct sockaddr{
sa_family_t sa_family; /* address family*/
char sa_data[]; /* variable-length address*/
...
};
套接字实现可以自由地添加额外的成员并且定义sa_data成员的大小。例如在linux中,该结构定义如下
struct sockaddr{
sa_family_t sa_family; /* address family*/
char sa_data[14]; /* variable-length address*/
};
其中sa_family_t表示套接字的通信域。主要有以下四个值
域 | 描述 |
AF_INET | IPv4因特网域 |
AF_INET6 | IPv6因特网域 |
AF_UNIX | UNIX域 |
AF_UNSPEC | 未指定 |
创建套接字的函数如下
#include <sys/socket.h>
int socket(int domain, int type, int protocol);/*成功返回文件(套接字)描述符,出错返回-1
其中domain指代通信域,type指代套接字类型,主要有以下四种
类型 | 描述 |
SOCK_DGRAM | 长度固定的、无连接的不可靠报文传递 |
SOCK_RAM | IP协议的数据报接口 |
SOCK_SEQPACKET | 长度固定、有序、可靠的面向连接报文传递 |
SOCK_STREAM | 有序、可靠、双向的面向连接字节流 |
参数protocol通常是零,表示按给定的域和套接字类型选择默认协议。当对同一域和套接字类型支持多个协议时,可以使用protocol参数选择一个特定协议。
一个多进程间利用UNIX域套接字(只用在本地)进行通信的例子( 代码分两部分不方便观察,后面socket_unix.c将其合为了一部分)
/*
domain_socket.h
@Author: duanjigang @2006-4-11
@Desp: declaratin of methods used for unix-domain-socket communication
*/
#ifndef _H_
#define _H_
#include <stdio.h>
#include <unistd.h>
#include <sys/un.h>
#include <sys/socket.h>
#define MSG_SIZE 1024
int init_send_socket(struct sockaddr_un * addr,char * path)
{
int sockfd,len;
sockfd=socket(AF_UNIX,SOCK_DGRAM,0);
if(sockfd<0)
{
exit(1);
}
bzero(addr,sizeof(struct sockaddr_un));
addr->sun_family=AF_UNIX;
strcpy(addr->sun_path,path);
return sockfd;
}
int init_recv_socket(char * path)
{
int sockfd,len;
struct sockaddr_un addr;
sockfd=socket(AF_UNIX,SOCK_DGRAM,0);
if(sockfd<0)
{
return -1;
}
bzero(&addr,sizeof(struct sockaddr_un));
addr.sun_family = AF_UNIX;
strcpy(addr.sun_path, path);
unlink(path);
len = strlen(addr.sun_path) + sizeof(addr.sun_family);
if(bind(sockfd,(struct sockaddr *)&addr,len)<0)
{
return -1;
}
return sockfd;
}
int receive_from_socket(int sockfd, char msg[])
{
int n;
memset(msg, 0, MSG_SIZE);
n=recvfrom(sockfd, msg, MSG_SIZE, 0, NULL, NULL);
if(n<=0)
{
return -1;
}
msg[n]=0;
return n;
}
int send_to_socket(int sockfd, char msg[], const struct sockaddr_un * addr)
{
int len;
len = strlen(addr->sun_path)+sizeof(addr->sun_family);
sendto(sockfd, msg, strlen(msg), 0, (struct sockaddr*)addr,len);
return 1;
}
#endif
Sender: message for 1 times
Sender: message for 2 times
Receiver: message for 2 times
Sender: message for 3 times
Receiver: message for 3 times
Sender: message for 4 times
Receiver: message for 4 times
Sender: message for 5 times
Receiver: message for 5 times
Sender: message for 1 times
Sender: message for 2 times
Receiver: message for 2 times
Sender: message for 3 times
Receiver: message for 3 times
Sender: message for 4 times
Receiver: message for 4 times
Sender: message for 5 times
Receiver: message for 5 times
socket_unix.c