谈谈Tcpserver开启多线程并发处理遇到的问题!

最近在学习最基础的socket网络编程,在Tcpserver开启多线程并发处理时遇到了一些问题!

说明

在linux以及Windows的共享文件夹进行编写的,所以代码中有的部分使用

cpp 复制代码
#ifdef WIN64
...
#else
...
#endif 

进入正题!!!

先来看看代码~

cpp 复制代码
#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++是支持多线程,但是需要注意以下三点:

  1. 必须包含头文件#include
  2. 必须有编译选项-std=c++11
  3. 必须有编译选项-pthread,否则运行出现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 能够保持向后兼容,并提高命令行的一致性。

小白初次学习,希望大佬们多多指教!!!

相关推荐
程序员-珍4 分钟前
虚拟机ip突然看不了了
linux·网络·网络协议·tcp/ip·centos
ぃ扶摇ぅ6 分钟前
Windows系统编程(三)进程与线程二
c++·windows
简单.is.good12 分钟前
【测试】接口测试与接口自动化
开发语言·python
Yvemil732 分钟前
MQ 架构设计原理与消息中间件详解(二)
开发语言·后端·ruby
程序员是干活的33 分钟前
私家车开车回家过节会发生什么事情
java·开发语言·软件构建·1024程序员节
什么鬼昵称37 分钟前
Pikachu- Over Permission-垂直越权
运维·服务器
我是陈泽1 小时前
一行 Python 代码能实现什么丧心病狂的功能?圣诞树源代码
开发语言·python·程序员·编程·python教程·python学习·python教学
码农小白1 小时前
linux驱动:(22)中断节点和中断函数
linux·运维·服务器
4647的码农历程1 小时前
Linux网络编程 -- 网络基础
linux·运维·网络
Mr.Z.4111 小时前
【历年CSP-S复赛第一题】暴力解法与正解合集(2019-2022)
c++