网络编程(二)
1、其他套接字操作函数(经常用于面向连接的通信过程和数据报通信过程):
(1)getsockname函数用于返回本地套接字地址;
int getsockname(int sockfd, struct sockaddr * address, socklen_t * address_len);
(2)getpeername用于获取一个套接字的远程对等套接字的地址;
int getpeername(int sockfd, struct sockaddr * address, socklen_t * address_len);
(3)send函数用于向已连接的套接字发送数据;
size_t send(int sockfd, const void * buffer, size_t length, int flags);
参数flags指明消息传送的类型,它的值要么是0,此时这个函数等价于write;要么由下述标志按位逻辑或操作而形成
参数flags的标志位:
值 | 含义 |
MSG_OOB | 导致send发送的数据成为带外数据 |
MSG_DONTROUTE | 不在消息中包含路由信息 |
(4)recv函数用于从已连接的套接字接收消息。
size_t recv(int sockfd, void * buffer, size_t length, int flags);
(5)read和write通常用来读写套接字上的普通数据,当需要发送或者接受特殊数据,如带外数据时,就必须使用send和recv才能做到。
2、例子
(1) StreamSocketClient2.c:发送带外数据的客户端程序
/* * StreamSocketClient2.c * * Created on: Aug 31, 2013 * Author: root */ #include <stdio.h> #include <sys/socket.h> #include <netinet/in.h> #include <netdb.h> #define PORT 6666 #define HOST_ADDR "127.0.0.1" int main(){ int sockfd, n; struct sockaddr_in servaddr; sockfd = socket(AF_INET, SOCK_STREAM, 0); if(sockfd < 0){ printf("Socket created failed.\n"); return -1; } servaddr.sin_family = AF_INET; servaddr.sin_port = htons(PORT); inet_aton(HOST_ADDR, &servaddr.sin_addr); printf("connecting.......\n"); if(connect(sockfd, (struct sockaddr*)&servaddr, sizeof(servaddr)) < 0){ printf("Connect Error.\n"); return -1; } write(sockfd, "123",3); printf("wrote 3 byte of normal data.\n"); sleep(1); send(sockfd, "a", 1, MSG_OOB); printf("wrote 1 byte of OOB data.\n"); sleep(1); write(sockfd, "56",2); printf("wrote 2 byteof normal data.\n"); sleep(1); send(sockfd, "b", 1, MSG_OOB); printf("Wrote 1 byte of OOB data.\n"); sleep(1); write(sockfd, "89",2); printf("wrote 2 byte of normal data.\n"); sleep(1); return 0; }
(2) StreamSocketServer2.c:接收带外数据的例子。
以下的接收程序使用SIGURG信号来获得带外数据的通知。当一套接字发现有一带外数据在途中时,会发送SIGURG信号给此套接字的拥有线程或线程组;为了捕获该信号,首先要利用系统函数signal设定处理SIGURG信号的函数并且调用fcntl设置连接套接字的拥有者。
/* * StreamSocketServer2.c * * Created on: Aug 31, 2013 * Author: root */ #include <sys/socket.h> #include <netinet/in.h> #include <netdb.h> #include <stdio.h> #include <signal.h> #include <fcntl.h> #include <unistd.h> #define LISTENQ 5 int listenfd, connfd; void sig_urg(int signo); int main(){ int n; char buff[100]; socklen_t len; struct sockaddr_in servaddr, cliaddr; if(signal(SIGURG, sig_urg) == -1){ printf("Couldn't register SIG_URG METHOD for SIGURG.\n"); return -1; } listenfd = socket(AF_INET, SOCK_STREAM, 0); if(listenfd < 0){ printf("Socket created failed.\n"); return -1; } servaddr.sin_family = AF_INET; servaddr.sin_port = htons(6666); servaddr.sin_addr.s_addr = htonl(INADDR_ANY); if(bind(listenfd, (struct sockaddr*)&servaddr, sizeof(servaddr)) < 0){ printf("bind failed.\n"); return -1; } printf("listening ...\n"); listen(listenfd, LISTENQ); len = sizeof(cliaddr); connfd = accept(listenfd, (struct sockaddr*)&cliaddr, &len); fcntl(connfd, F_SETOWN, getpid()); //设置连接套接字的拥有者 while(1){ if((n=read(connfd, buff, sizeof(buff))) == 0){ printf("received EOF\n"); return 0; } buff[n] = 0; printf("read %d bytes : %s\n", n,buff); } } void sig_urg(int signo){ int n; char buffer[100]; printf("SIGURG received\n"); n = recv(connfd,buffer, sizeof(buffer), MSG_OOB); buffer[n] = 0; printf("read %d OOB byte: %s\n", n,buffer); }
程序运行结果: