recvmsg()/sendmsg()函数是socket编程中最常用的函数。其他IO函数能实现的一切功能recvmsg()/sendmsg()都可实现,下面是一个简单的例子
服务端
#include <iostream>
#include<sys/types.h>
#include<sys/socket.h>
#include<signal.h>
#include<string.h>
#include <arpa/inet.h>
#include <unistd.h>
#include<stdlib.h>
#include<stdio.h>
using namespace std;
void do_SIGINT(int param);
void do_SIGPIPE(int param);
void handler_client(int _client_fd);
const static int PORT = 8888;
const static int WAITING=5;
const static int MSG_NUM=3;
const static int MSG_SIZE=10;
int server_fd;
int main()
{
signal(SIGINT,do_SIGINT);
signal(SIGPIPE,do_SIGPIPE);
server_fd=socket(AF_INET,SOCK_STREAM,0);
if(server_fd<0){
cout<<"socket error\n";
return -1;
}
sockaddr_in server_addr;
bzero(&server_addr,sizeof(server_addr));
server_addr.sin_family=AF_INET;
server_addr.sin_addr.s_addr=htonl(INADDR_ANY);
server_addr.sin_port=htons(PORT);
int err=bind(server_fd,(sockaddr*)&server_addr,sizeof(server_addr));
if(err<0){
cout<<"bind error\n";
return -1;
}
err=listen(server_fd,WAITING);
if(err<0){
cout<<"listen error\n";
return -1;
}
int client_fd;
sockaddr_in client_addr;
socklen_t len=sizeof(sockaddr);
bzero(&client_addr,sizeof(client_addr));
int pid=-1;
while(true){
if(pid==0)
break;
cout<<"wait for new client"<<endl;
client_fd=accept(server_fd,(sockaddr*)&client_addr,&len);
if(client_fd<0){
cout<<server_fd<<endl;
perror("client conn fail\n");
continue;
}
pid=fork();
if(pid==-1){
close(client_fd);
cout<<"client conn fail\n";
continue;
}
if(pid==0){
close(server_fd);
cout<<"sub prog handler client fd\n";
handler_client(client_fd);
}else{
close(client_fd);
cout<<"main prog close client fd\n";
}
}
}
void do_SIGINT(int sig){
cout<<"catch a SIGINT\n";
close(server_fd);
_exit(0);
}
void do_SIGPIPE(int sig){
cout<<"catch a SIGPIPE\n";
}
void handler_client(int _client_fd){
msghdr msg;
//由于在TCP持有连接状态的,所以连接两端的地址和端口都很明确,故这两个参数不生效
//但是由于UDP是无连接状态的,所以这两个参数将在UDP连接中有效
msg.msg_name=NULL;
msg.msg_namelen=0;
msg.msg_control=NULL;
msg.msg_controllen=0;
msg.msg_iov=NULL;
msg.msg_iovlen=30;
msg.msg_flags=0;
msg.msg_iov=(iovec *)malloc(MSG_NUM*sizeof(iovec));
int i;
for(i=0;i<MSG_NUM;i++){
msg.msg_iov[i].iov_base=(char*)malloc(MSG_SIZE);
msg.msg_iov[i].iov_len=MSG_SIZE;
}
int size;
char* output;
while(true){
size=recvmsg(_client_fd,&msg,0);
if(size<1)
{
if(size==0)
close(_client_fd);
break;
}
cout<<"rec size is "<<size<<endl;
cout<<"------------------------start"<<endl;
for(i=0;i<MSG_NUM;i++){
cout<<"------------------------>"<<endl;
cout<<"msg length is "<<msg.msg_iov[i].iov_len<<endl;
output=(char*)malloc(msg.msg_iov[i].iov_len+1);
bzero(output,msg.msg_iov[i].iov_len+1);
memcpy(output,msg.msg_iov[i].iov_base,msg.msg_iov[i].iov_len);
cout<<output<<"|"<<endl;
free(output);
cout<<"<------------------------"<<endl;
}
cout<<"------------------------end"<<endl;
}
for(i=0;i<MSG_NUM;i++){
free( msg.msg_iov[i].iov_base);
}
free(msg.msg_iov);
free(msg.msg_name);
}
客户端
#include <iostream>
#include<sys/types.h>
#include<sys/socket.h>
#include<signal.h>
#include<string.h>
#include <arpa/inet.h>
#include <unistd.h>
#include<stdlib.h>
#include<stdio.h>
using namespace std;
const static int PORT = 8888;
const static int MSG_NUM=3;
const static int MSG_SIZE=10;
const static string SERVER_IP="192.168.163.143";
void do_SIGINT(int param);
void do_SIGPIPE(int param);
void do_client(int _server_fd);
int from_server_fd;
int main()
{
signal(SIGINT,do_SIGINT);
signal(SIGPIPE,do_SIGPIPE);
from_server_fd=socket(AF_INET,SOCK_STREAM,0);
if(from_server_fd<0){
cout<<"socket error\n";
return -1;
}
sockaddr_in server_addr;
bzero(&server_addr,sizeof(server_addr));
server_addr.sin_family=AF_INET;
//server_addr.sin_addr.s_addr=htonl(INADDR_ANY);
server_addr.sin_addr.s_addr=inet_addr(SERVER_IP.c_str());
server_addr.sin_port=htons(PORT);
connect(from_server_fd,(sockaddr*)&server_addr,sizeof(sockaddr));
do_client(from_server_fd);
close(from_server_fd);
}
void do_SIGINT(int sig){
cout<<"catch a SIGINT\n";
close(from_server_fd);
_exit(0);
}
void do_SIGPIPE(int sig){
cout<<"catch a SIGPIPE\n";
}
void do_client(int _server_fd){
msghdr msg;
//由于在TCP持有连接状态的,所以连接两端的地址和端口都很明确,故这两个参数不生效
//但是由于UDP是无连接状态的,所以这两个参数将在UDP连接中有效
msg.msg_name=NULL;
msg.msg_namelen=0;
msg.msg_control=NULL;
msg.msg_controllen=0;
msg.msg_iov=NULL;
msg.msg_iovlen=30;
msg.msg_flags=0;
msg.msg_iov=(iovec *)malloc(MSG_NUM*sizeof(iovec));
int i;
for(i=0;i<MSG_NUM;i++){
msg.msg_iov[i].iov_base=(char*)malloc(MSG_SIZE);
msg.msg_iov[i].iov_len=MSG_SIZE;
}
while(true){
for(i=0;i<MSG_NUM;i++){
string input;
cin>>input;
cout<<"input is "<<input<<" length is "<<input.size()<<endl;
memcpy(msg.msg_iov[i].iov_base,input.c_str(),input.size());
msg.msg_iov[i].iov_len=input.size();
}
sendmsg(_server_fd,&msg,0);
}
free(msg.msg_iov);
free(msg.msg_name);
}