c++网络编程的若干个小问题

HW_Coder0501 2016-12-29 08:40:39
以下是c++实现的socket聊天室的程序,有几个问题不是很理解,请诸位大神帮忙解答!问题相关的部分已在代码中用红色标出。

(1)、client.c中的SendMsg函数中的msg只是一个字符串,为什么它会有size()函数msg.size()可以调用?
(2)、client.c中的std::thread(RMsg).detach(); 语句该怎么理解?我只知道thread有如下形式的使用方法:std::thread t(my_thread);,这种在thread后直接加(函数名)的用法确实不知道,而且网上我也没找到这样的用法。


(3)、server.c中的RecvMsg()用到了容器的erase函数cli_vec.erase(pos),这部在文中有什么作用?
(4)、server.c中的SendMsg()函数中if(*i == acceptfd)之后为什么会continue?


/* client.c */

#include <iostream>
#include <arpa/inet.h>
#include <unistd.h>
#include <thread>
#include <string>
#include <cstring>

using namespace std;


void SendMsg(const string &msg)
{
if(send(sockfd, msg.c_str(), msg.size(), 0)== -1)
cout<<"Failed to send"<<endl;
}

void RMsg()
{
int len;
char recv_buf[1024];

while (1)
{
memset(recv_buf, 0, sizeof(recv_buf));
len = recv(sockfd, recv_buf, sizeof(recv_buf), 0);
if (len == -1)
{
cout<<"Failed to recv"<<endl;
}
if(len == 0)
{
close(sockfd);
cout<<"与服务器断开连接!"<<endl;
break;
}
cout<<"Receive message: "<<recv_buf<<endl;
}
}

int main()
{
string ip = "127.0.0.1";
int sockfd;
struct sockaddr_in serv_addr;
int port;
cout<<"please input server port:";
cin>>port;

sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd == -1)
{
cout<<"Failed to sockfd"<<endl;
return -1; //exit(1)?
}

memset(&serv_addr, 0, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(port); //Host to Network Long
serv_addr.sin_addr.s_addr = inet_addr(ip.c_str()); //const char *c_str();

int stat = connect(sockfd, (struct sockaddr *) &serv_addr,sizeof(serv_addr));
if (stat ==-1)
{
cout<<"Failed to connect"<<endl;
return -1;
}

std::thread(RMsg).detach(); //c++11中的用于线程操作的类std::thread
while(1)
{
string send_msg;

cin>>send_msg;
if (send_msg == "q")
{
cout<<"结束客户端!"<<endl;
break;
}
else
SendMsg(send_msg);
}
close(sockfd);
return 0;
}

....................................................................................................................................

/* server.c */

#include <iostream>
#include <thread>
#include <arpa/inet.h>
#include <cstring>
#include <vector>
#include <algorithm>
#include <unistd.h>
using namespace std;
vector<int> cli_vec;
int listenfd, port;
const char *ip = "127.0.0.1";
void SendMsg(char* buf, int connfd)
{
//cout<<"now send..."<<endl;
char *data = buf;
int len;
for(auto i=cli_vec.begin(); i!=cli_vec.end(); ++i)
{
if(*i == connfd) continue;
if((len=send(*i, data, strlen(data),0)) == -1)
{
//cout<<"send error"<<endl;
}else{
//cout<<"Send: "<<data<<endl;
}
}
}

void RecvMsg(int connfd)
{
int len;
char buf[100];
while(1)
{
memset(buf, 0, sizeof(buf));
//cout<<"now receive..."<<connfd<<endl;
if((len = recv(connfd, buf,sizeof(buf), 0)) == -1)
{
//cout<<"Falid to receive"<<endl;
}

if(0 == len)
{
cout<<connfd<<" has exit the chatting room"<<endl;
auto pos = find(cli_vec.begin(), cli_vec.end(), connfd);
if(pos != cli_vec.end())
{
cli_vec.erase(pos);
}

break;
}
SendMsg(buf,connfd);
}
}

void WaitQuit()
{
char buf[100];
while(1)
{
cin>>buf;
if(0 == strcmp(buf,"q"))
{
for(auto i=cli_vec.begin(); i!=cli_vec.end(); i++)
{
close(*i);
}
cli_vec.clear();
close(listenfd);
break;
}
}
exit(0);
}

int main()
{
if((listenfd=socket(AF_INET,SOCK_STREAM,0)) == -1)
{
cout<<"socket error"<<endl;
return -1;
}
cout<<"请输入端口号:";
cin>>port;
struct sockaddr_in serv_addr,cli_addr;

memset(&serv_addr, 0, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(port);
serv_addr.sin_addr.s_addr = inet_addr(ip);

if(bind(listenfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) == -1)
{
cout<<"bind error"<<endl;
return -1;
}
if(listen(listenfd, 10) == -1)
{
cout<<"listen error"<<endl;
return -1;
}
std::thread(WaitQuit).detach();
cout<<"server is running..."<<endl;

while(1)
{
size_t cli_len = sizeof(cli_addr);
memset(&cli_addr, 0, cli_len);

int connfd = accept(listenfd, (struct sockaddr*)&cli_addr, &cli_len);

if(connfd == -1)
{
cout<<"accept error"<<endl;
return -1;
}
cout<<connfd<<" has enter the chatting room"<<endl;
cli_vec.push_back(connfd);
std::thread(RecvMsg, connfd).detach();
}
return 0;
}


...全文
371 4 打赏 收藏 转发到动态 举报
写回复
用AI写文章
4 条回复
切换为时间正序
请发表友善的回复…
发表回复
nswcfd 2017-01-03
  • 打赏
  • 举报
回复
http://en.cppreference.com/w/cpp/thread/thread/thread
HW_Coder0501 2017-01-01
  • 打赏
  • 举报
回复
引用 2 楼 nswcfd 的回复:
1. string是个类/class,string::size是它的一个方法。 2. 先调用thread对象的构造函数,然后在返回的(临时)thread对象上调用detach方法,类比std::string("test").size()。 3. read/recv返回0表示EOF,即连接关闭,这里把连接fd从容器中移除。与之对应的是main循环里把fd放入容器。 4. sendMsg是实现广播功能吧,自然就不需要给自己发送了。
元旦好~多谢指点。std::thread(RMsg).detach(); 语句中的构造函数是哪一个?如下形式的语句:std::thread t(my_thread);构造函数又是哪一个?
nswcfd 2016-12-30
  • 打赏
  • 举报
回复
1. string是个类/class,string::size是它的一个方法。 2. 先调用thread对象的构造函数,然后在返回的(临时)thread对象上调用detach方法,类比std::string("test").size()。 3. read/recv返回0表示EOF,即连接关闭,这里把连接fd从容器中移除。与之对应的是main循环里把fd放入容器。 4. sendMsg是实现广播功能吧,自然就不需要给自己发送了。

23,120

社区成员

发帖
与我相关
我的任务
社区描述
Linux/Unix社区 应用程序开发区
社区管理员
  • 应用程序开发区社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧