Sockets sendmsg()不';t按预期运行
我用一对简单的客户机和服务器编写了一个程序,第一个程序生成一组字符串并通过socket提供的API发送,即sendmsg(),第二个程序通过epoll接收字符串 根据tcpdump捕获的内容和客户端执行的结果,客户端能够连接到服务器并正确发送几条消息,但只有少数几条,以下字符串未能完全接收,并且在服务器打印接收到的代码结束时,同一字符串段存在无限重复 如果需要更多详细信息,请与我联系 顺便问一下,是否有任何推荐的参考文献提供了有关sendmsg()用法的详细说明 这是客户端的主要代码:Sockets sendmsg()不';t按预期运行,sockets,unix,Sockets,Unix,我用一对简单的客户机和服务器编写了一个程序,第一个程序生成一组字符串并通过socket提供的API发送,即sendmsg(),第二个程序通过epoll接收字符串 根据tcpdump捕获的内容和客户端执行的结果,客户端能够连接到服务器并正确发送几条消息,但只有少数几条,以下字符串未能完全接收,并且在服务器打印接收到的代码结束时,同一字符串段存在无限重复 如果需要更多详细信息,请与我联系 顺便问一下,是否有任何推荐的参考文献提供了有关sendmsg()用法的详细说明 这是客户端的主要代码: void
void MultithreadedLogAnalyzer::SendToServer(string Addr,uint16_t Port) {
int connfd = socket(AF_INET,SOCK_STREAM,0);
sockaddr_in servaddr;
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(Port);
inet_pton(AF_INET,Addr.c_str(),&servaddr.sin_addr);
/*connect failure process to be added*/
int st = connect(connfd,(struct sockaddr *)&servaddr,sizeof(sockaddr));
if(-1 == st){
perror("connection failed");
}
Handle(connfd,servaddr);
close(connfd);
}
void MultithreadedLogAnalyzer::Handle(int connfd,const sockaddr_in &servaddr){
int n= 0,counter =0;
for(vector<string>::iterator si = mFilterResult.begin();si != mFilterResult.end(); ++si)
{
msghdr msg;
iovec iov;
memset(&msg,0,sizeof(msg));
memset(&iov,0,sizeof(iov));
msg.msg_control = NULL;
msg.msg_controllen = 0;
msg.msg_flags = 0;
char data[1024];
memset(data,0, 1024);
memcpy(data,si->c_str(),si->size());
iov.iov_base = data;
iov.iov_len = (*si).size() ;//check first to locate error
cout << "size:" << (*si).size() << endl;
msg.msg_name = NULL;
msg.msg_namelen = 0;
msg.msg_iov = &iov;
msg.msg_iovlen = 1;
//msg.msg_accrights = NULL;
//msg.msg_accrightslen = 0;
n = sendmsg(connfd,&msg,0);
cout << "n: " << n << endl;
++counter;
if (-1 == n)
perror("sendmsg error\n");
}
cout << "number of strings send: " << counter << endl;
void multi-threadedloganalyzer::SendToServer(字符串地址,uint16\u t端口){
int connfd=套接字(AF_INET,SOCK_STREAM,0);
servaddr中的sockaddr_;
servaddr.sin_family=AF_INET;
servaddr.sinu端口=htons(端口);
inet_pton(AF_inet,Addr.c_str(),&servaddr.sin_Addr);
/*要添加的连接失败进程*/
int st=connect(connfd,(struct sockaddr*)和servaddr,sizeof(sockaddr));
如果(-1==st){
perror(“连接失败”);
}
手柄(connfd、servaddr);
关闭(connfd);
}
void multi-threadedLogAnalyzer::Handle(int-connfd,const-sockaddr\u in&servaddr){
int n=0,计数器=0;
对于(向量::迭代器si=mFilterResult.begin();si!=mFilterResult.end();+si)
{
msghdr msg;
iovec-iov;
memset(&msg,0,sizeof(msg));
memset(&iov,0,sizeof(iov));
msg.msg_control=NULL;
msg.msg_controllen=0;
msg.msg_标志=0;
字符数据[1024];
memset(数据,0,1024);
memcpy(data,si->c_str(),si->size());
iov.iov_base=数据;
iov.iov_len=(*si).size();//首先检查以查找错误
库特
这是在错误的位置。它应该是在c=recvmsg(…)之后立即进行的测试;
如果(c>0)
,那么它应该是,如果c==-1
,那么您应该立即调用perror()
,或者在消息中使用errno
或strerror()
,而不调用任何其他系统调用
基本上,您在流结束后继续接收;在流结束后打印垃圾或错误;并且在打印邮件时忽略了实际邮件长度。非常感谢您的回答,尽管我已经解决了我的问题。问题是由于重复发送邮件而导致的,对其行为没有任何控制,而h似乎已超过TCP发送窗口限制,并导致我无法理解结果。该问题是由于忽略流的结尾和消息长度造成的。recvmsg()
在流的结尾返回零。此时停止。如果出现错误,也会停止,如果出现错误,则调用peror()
,或在消息中使用errno
或strerror()
。我确实忽略了流的结尾,但这没问题,因为msg是用值0初始化的,不会打印任何内容,并且不会或已经在此处发生错误。字符串结尾由“\0”标记,当c_str()我打电话给你了。你可以试一试。谢谢你的进一步解释。
#include <sys/socket.h>
#include <stdlib.h>
#include <iostream>
#include <string.h>
#include <fcntl.h>
#include <stdio.h>
#include <strings.h>
#include <netinet/in.h>
#include <sys/epoll.h>
#define POLLSIZE 100
#define STRINGSIZE 300
using namespace std;
void handle(int fd){
int c = 0;
do{
msghdr msg;
memset(&msg,0,sizeof(msghdr));
msg.msg_name = NULL;
msg.msg_namelen = 0;
char data[1024];
iovec iov;
iov.iov_base = data;
iov.iov_len = 1024;
msg.msg_iov = &iov;
msg.msg_iovlen = 1;
msg.msg_control = NULL;
msg.msg_controllen = 0;
msg.msg_flags = 0;
c = recvmsg(fd,&msg,0);
if(msg.msg_iovlen==0
){
return;
}
cout << "msg length:" << msg.msg_iovlen<< endl;
cout << string((char *)(msg.msg_iov[0].iov_base)) << endl;
}while(c != -1);
}
int main() {
int listenfd;
listenfd = socket(AF_INET, SOCK_STREAM, 0);
sockaddr_in servaddr,cliaddr;
socklen_t socklen = 0;
bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
int serverPort = 2000;
servaddr.sin_port = htons(serverPort);
bind(listenfd,(struct sockaddr *)&servaddr,sizeof(servaddr));
int listennumnber = 20;
listen(listenfd,listennumnber);
//the rest to be commented
int epfd = epoll_create(POLLSIZE);
if (epfd < 0)
perror("epoll_create");
struct epoll_event ev;
ev.events = EPOLLIN|EPOLLET;
ev.data.fd = listenfd;
if(epoll_ctl(epfd,EPOLL_CTL_ADD,listenfd,&ev) < 0)
perror("epoll_ctl");
int curfds = 1;
struct epoll_event *events = (struct epoll_event*)malloc(sizeof(struct epoll_event));
for (;;){
int n;
int nfds = epoll_wait(epfd,events,curfds,-1);
if (-1 == nfds)
continue;
for(n = 0;n < nfds; ++n){
if(events[n].data.fd == listenfd){
int connfd = accept(listenfd,(struct sockaddr *)&cliaddr ,&socklen);
cout << "connect established through connfd: " << connfd << endl;
if (connfd < 0)
continue;
// if(setnonblocking(connfd) < 0)
// perror("set setnonblocking error");
ev.events = EPOLLIN | EPOLLET;
ev.data.fd = connfd;
if(epoll_ctl(epfd,EPOLL_CTL_ADD,connfd,&ev) < 0)
return -1;
curfds++;
continue;
}
handle(events[n].data.fd);
}
}
return 0;
}
cout << "msg length:" << msg.msg_iovlen<< endl;
cout << string((char *)(msg.msg_iov[0].iov_base)) << endl;
}while(c != -1);