linux IPC socket(2)

使用bind来关联地址和套接字

#include <sys/types.h>
#include <sys/socket.h>

int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
返回值:成功0,出错-1
sockfd:已经建立的socket描述符
addr:指向sockaddr的结构体指针
addrlen:addr结构的长度

 

getsockname函数来发现绑定到套接字上的地址

#include <sys/socket.h>

int getsockname(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
返回值:成功0,出错-1
sockfd:已经建立的socket描述符
addr:指向sockaddr的结构体指针
addrlen:addr结构的长度

 

如果套接字已经和对等方连接,可以调用getpeername函数来找到对方的地址

#include <sys/socket.h>

int getpeername(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
返回值:成功0,出错-1
sockfd:已经建立的socket描述符
addr:指向sockaddr的结构体指针
addrlen:addr结构的长度

 

使用connect函数来建立连接

#include <sys/types.h>
#include <sys/socket.h>

int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
返回值:成功0,出错-1
sockfd:已经建立的socket描述符 
addr:指向sockaddr的结构体指针
addrlen:addr结构的长度

 

服务器调用listen函数来宣告它愿意接收连接请求

#include <sys/types.h>
#include <sys/socket.h>

int listen(int sockfd, int backlog);
返回值:成功0,出错-1
sockfd:已经建立的socket描述符
backlog:等待连接队列的最大长度

 

使用accept函数获取连接请求并建立连接

#include <sys/types.h>
#include <sys/socket.h>

int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
返回值:成功文件(套接字)描述符,出错-1
sockfd:已经建立的socket描述符 
addr:指向sockaddr的结构体指针
addrlen:addr结构的长度

 

send和write很像,但是可以指定标志来改变处理传输数据的方式

#include <sys/types.h>
#include <sys/socket.h>

ssize_t send(int sockfd, const void *buf, size_t len, int flags);
返回值:成功返回发送字节数,出错-1
sockfd:socket描述符
len:缓冲区数据长度
flags:调用执行方式

 

sendto可以在无连接的套接字上指定一个目标地址

#include <sys/types.h>
#include <sys/socket.h>

ssize_t sendto(int sockfd, const void *buf, size_t len, int flags, const struct sockaddr *dest_addr, socklen_t addrlen);
返回值:成功发送的字节数,出错-1
sockfd:socket描述符
buf:带发送数据缓冲区
len:缓冲区长度
flags:调用方式标志位,一般为0
dest_addr:指向目的套接字地址
addrlen:所指地址长度

 

可以调用带有msghdr结构的sendmsg来指定多重缓冲区传输数据,这和writev函数很相似

#include <sys/types.h>
#include <sys/socket.h>

ssize_t sendmsg(int sockfd, const struct msghdr *msg, int flags);
返回值:成功发送的字节数,出错-1
sockfd:socket描述符
msg:信息头结构指针
flags:可选标记参数位,和send或是sendto参数相同

msghdr结构

struct msghdr {
               void         *msg_name;       /* optional address */
               socklen_t     msg_namelen;    /* size of address */
               struct iovec *msg_iov;        /* scatter/gather array */
               size_t        msg_iovlen;     /* # elements in msg_iov */
               void         *msg_control;    /* ancillary data, see below */
               size_t        msg_controllen; /* ancillary data buffer len */
               int           msg_flags;      /* flags (unused) */
};
struct msghdr

 

函数recv和read相似,但是recv可以指定标志来控制如何接收数据

#include <sys/types.h>
#include <sys/socket.h>

ssize_t recv(int sockfd, void *buf, size_t len, int flags);
返回值:数据字节长度,若无可用数据或对等方已经按序结束返回0,出错-1
sockfd:socket描述符
buf:接收数据缓冲
len:buf的长度
flags:可选标记位

 

如果发送者已经调用shutdown来结束传输,或者网络协议支持按默认的顺序关闭并且发送端已经关闭,那么当所有的数据接收完毕后,recv会返回0

如果兴趣定位发送者,可以使用recvfrom来得到数据发送者的源地址

#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);
返回值:返回数据字节长度,若无可用数据或对等方已经按序结束,返回0,出错-1
sockfd:socket描述符
buf:及诶手数据缓冲
len:buf长度
flags:可选标记位
src_addr:如果非空,它将包含数据发送者的套接字端点地址
addrlen:src_addr参数长度

 

为了将数据送入多个缓冲区,或者想接收辅助数据,可以使用recvmsg

#include <sys/types.h>
#include <sys/socket.h>

ssize_t recvmsg(int sockfd, struct msghdr *msg, int flags);
返回值:返回数据的自及诶长度,若无可用数据或对等方已经按序结束,返回0,出错-1
sockfd:socket描述符
msg:信息头结构指针
flags:可选标志位

 

可以使用setsockopt函数来设置套接字选项

#include <sys/types.h>
#include <sys/socket.h>

int setsockopt(int sockfd, int level, int optname, const void *optval, socklen_t optlen);
返回值:成功0,失败-1
sockfd:socket描述符
level:标识了选项应用的协议
optname:需要设置的选项
optval:指向存放选项值的缓冲区指针
optlen:optval的长度

 

可以使用getsockopt函数来查看选项的当前值

#include <sys/types.h>
#include <sys/socket.h>

int getsockopt(int sockfd, int level, int optname, void *optval, socklen_t *optlen);
返回值:成功0,失败-1
sockfd:socket描述符
level:标识了选项应用的协议
optname:需要设置的选项
optval:指向存放选项值的缓冲区指针
optlen:指向optval缓冲区的长度

 TCP例程:

服务器端:

 1 #include <stdio.h>
 2 #include <stdlib.h>
 3 #include <sys/types.h>
 4 #include <sys/socket.h>
 5 #include <netinet/in.h>
 6 #include <arpa/inet.h>
 7 #include <string.h>
 8 
 9 #define MAXLINE 80
10 #define SERV_PORT 8000
11 
12 int main(void)
13 {
14         char buf[MAXLINE];
15         int listenfd = 0;
16 
17         listenfd = socket(AF_INET, SOCK_STREAM, 0);
18 
19         struct sockaddr_in servaddr = {0};
20         servaddr.sin_family = AF_INET;
21         servaddr.sin_port = htons(SERV_PORT);
22         servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
23 
24         bind(listenfd, (struct sockaddr *)&servaddr, sizeof(servaddr));
25         listen(listenfd, 20);
26 
27         printf("Accepting connections ...\n");
28         while(1)
29         {
30                 struct sockaddr_in cliaddr = {0};
31                 socklen_t cliaddr_len = sizeof(cliaddr);
32                 int connfd = accept(listenfd, (struct sockaddr *)&cliaddr, &cliaddr_len);
33 
34                 char str[INET_ADDRSTRLEN];
35                 printf("connect from %s at PORT %d\n",
36                                 inet_ntop(AF_INET, &cliaddr.sin_addr, str, sizeof(str)),
37                                 ntohs(cliaddr.sin_port));
38                 while(1)
39                 {
40                         int count = read(connfd, buf, MAXLINE);
41                         if(count == 0)
42                                 break;
43 
44                         write(connfd, buf, count);
45                 }
46                 close(connfd);
47                 printf("closed from %s at PORT %d\n",
48                                 inet_ntop(AF_INET, &cliaddr.sin_addr, str, sizeof(str)),
49                                 ntohs(cliaddr.sin_port));
50         }
51 }
server.c

客户端:

 1 #include <stdio.h>
 2 #include <arpa/inet.h>
 3 #include <stdlib.h>
 4 #include <unistd.h>
 5 #include <sys/socket.h>
 6 #include <netinet/in.h>
 7 
 8 #define MAXLINE 80
 9 #define SERV_PORT 8000
10 #define MESSAGE "hello world"
11 
12 int main(int argc, char *argv[])
13 {
14         char buf[MAXLINE];
15 
16         int sockfd = socket(AF_INET, SOCK_STREAM, 0);
17 
18         struct sockaddr_in servaddr = {0};
19         servaddr.sin_family = AF_INET;
20         inet_pton(AF_INET, "127.0.0.1", &servaddr.sin_addr);
21         servaddr.sin_port = htons(SERV_PORT);
22 
23         if(connect(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr)) != 0)
24         {
25                 printf("connected failed");
26                 return 1;
27         }
28 
29         write(sockfd, MESSAGE, sizeof(MESSAGE));
30         int count = read(sockfd, buf, MAXLINE);
31 
32         printf("Response from server: %s\n", buf);
33 
34         close(sockfd);
35         return 0;
36 }
client.c

 

posted @ 2017-12-22 10:36  习惯就好233  阅读(177)  评论(0编辑  收藏  举报