赞
踩
最近在学习最基础的socket网络编程,在Tcpserver开启多线程并发处理时遇到了一些问题!
在linux以及Windows的共享文件夹进行编写的,所以代码中有的部分使用
#ifdef WIN64
...
#else
...
#endif
进入正题!!!
先来看看代码~
#include <string.h> #include <stdlib.h> #include <stdio.h> #ifdef _WIN64 #include<windows.h> #define socklen_t int #else #include <sys/types.h> #include <sys/socket.h> #include <unistd.h> #include <arpa/inet.h> #define closesocket close //因为linux和Windows下不同,所以定义了一个宏 #endif #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';//在结尾加\0 if (strstr(buf, "quit") != NULL) { char re[] = "quit success\n"; send(client, re, strlen(re) + 1, 0); break; } int sendlen = send(client, "ok\n", 4, 0); printf("recv %s\n", buf); } closesocket(client); //关闭 delete this;//要确保TcpThread 是new出来的 } int client = 0; }; #include<stdio.h> int main( int argc, char *argv[]) { #ifdef WIN64 WSADATA ws; WSAStartup(MAKEWORD(2, 2), &ws); #endif // WIN64 int sock=socket(AF_INET, SOCK_STREAM, 0); if (sock == -1) { printf("create socket failed!\n"); return -1; } printf("[%d]", sock); unsigned short port = 8080; if (argc > 1) //如果输入端口,则使用输入的,否则用8080 { port = atoi(argv[1]);//传递端口号 } sockaddr_in saddr; saddr.sin_family = AF_INET; saddr.sin_port = htons(port);//小端转大端 saddr.sin_addr.s_addr = htonl(0); if (::bind(sock, (sockaddr*)&saddr, sizeof(saddr)) != 0){ printf("bind port %d faild!\n", port); return -2; } else { printf("bind port %d success!\n", port); } listen(sock, 10); for (;;) { sockaddr_in caddr; socklen_t len = sizeof(caddr); int client = accept(sock, (sockaddr* ) & caddr, &len); if (client <= 0) break; printf("accept client %d\n", client); char *ip = inet_ntoa(caddr.sin_addr); unsigned short cport = ntohs(caddr.sin_port); printf("client ip is %s,port is %d\n", ip, cport); TcpThread *th = new TcpThread(); //new出来 th->client = client;//传入创建好的client thread sth(&TcpThread::Main, th);//启动线程 sth.detach();//释放主线程拥有的子线程的资源 } closesocket(sock); //#if WIN64 // closesocket(sock); // closesocket(client); //#else // close(sock); // close(sock); //#endif // WIN64 return 0; }
这时候直接在linux在make main
会报错
这说明我们使用c++11,这里我们需要写一个makefile,接着我们
vim makefile
在里面我们写如下代码:
然后在make
,这里发现成功了,然后./tcpserver
尝试创建多个线程, 在主线程发现成功了
用户开始连接,就报错
这时候我们就要注意了,是makefile里面缺少 -pthread
;
接着在编译运行,发现成功了!!!
打开两个端口telnet 192.168.xxx.xxx 8081
连接成功如下:
分别在两个里面发送消息1,2,收到了回复
然后主线程收到消息,表示成功了!
C++是支持多线程,但是需要注意以下三点:
Enable multithreading to use std::thread: Operation not permitted
。同时-lpthread和-pthread一样,但是建议使用-pthread。因为编译选项中指定 -pthread 会附加一个宏定义 -D_REENTRANT,该宏会导致 libc 头文件选择那些thread-safe的实现;链接选项中指定 -pthread 则同 -lpthread 一样,只表示链接 POSIX thread 库。由于 libc 用于适应 thread-safe 的宏定义可能变化,因此在编译和链接时都使用 -pthread 选项而不是传统的 -lpthread 能够保持向后兼容,并提高命令行的一致性。小白初次学习,希望大佬们多多指教!!!
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。