【】一个小例子,用到了c++11的线程库、优雅的断开套接字
#include <iostream>
#include <unistd.h>
#include <sys/socket.h>
#include <string.h>
#include <arpa/inet.h>
#include <thread>
using namespace std;
//在新建连接的时候创建线程
class TcpThread
{
public:
void Main() //入口函数
{
char buf[1024] = {0};
for (;;)
{
int recvlen = recv(client, buf, sizeof(buf) - 1, 0);
if (recvlen <= 0)
break;
buf[recvlen] = '\0';
if (strstr(buf, "quit"))
{
char re[] = "quit success!\n";
send(client, re, strlen(re), 0);
break;
}
int sendlen = send(client, "ok\n", 3, 0);
cout << "recv :" << buf << endl;
}
shutdown(client, SHUT_RDWR); //RD关闭想客户端读,WR关闭想客户端写
delete this; //自己删除自己,保证是new出来的
}
int client = 0;
};
int main(int argc, char *argv[])
{
int sock = socket(AF_INET, SOCK_STREAM, 0);
if (sock == -1)
{
cout << "create socket failed!" << endl;
return -1;
}
unsigned short port = 8080;
if (argc > 1)
{
port = atoi(argv[1]);
}
sockaddr_in saddr;
saddr.sin_family = AF_INET;
//协议
saddr.sin_port = htons(port);
//大端小端之间的转换,主机字节序转为网络字节序
saddr.sin_addr.s_addr = htonl(0);
//绑定ip地址
if (bind(sock, (sockaddr *)&saddr, sizeof(saddr)) != 0)
{
cout << "bind port faild:" << port << endl;
return -2;
}
cout << "bind port success:" << port << endl;
listen(sock, 10);
for (;;)
{
sockaddr_in caddr;
socklen_t len = 0;
int client = accept(sock, (sockaddr *)&caddr, &len);
if (client <= 0)
break;
cout << "accept client :" << client << endl;
char *ip = inet_ntoa(caddr.sin_addr);
unsigned short cport = ntohs(caddr.sin_port); //将网络字节序转为本地字节序
cout << "client ip is:" << ip << " port is:" << cport << endl;
//接受完连接创建一个线程
TcpThread *th = new TcpThread();
th->client = client;
thread sth(&TcpThread::Main, th);
//主线程不去对子线程进行任何操作,不做任何处理,释放主线程拥有的子线程资源
sth.detach();
}
shutdown(sock, SHUT_RDWR);
return 0;
}
【】:shutdown函数
1.SHUT_RD:值为0,关闭连接的读这一半。
2.SHUT_WR:值为1,关闭连接的写这一半。
3.SHUT_RDWR:值为2,连接的读和写都关闭。
终止网络连接的通用方法是调用close函数。但使用shutdown能更好的控制断连过程(使用第二个参数)。