我有一个服务器/客户端应用程序,多个客户端连接到服务器并发送数据,这些数据会根据threadNo分割并显示在不同的字段中。
只要main.cpp中没有线程,我的代码工作正常,但是只要我在main.cpp中启动一个线程以接受输入并同时运行服务器,我就拥有了在我的connection.cpp中设置开始表现得非常奇怪。没有重叠的名字。
使用断点我发现有时connection.cpp中的新线程不会传递它们的数据结构,有时它们会传递。无论如何,当客户端尝试连接时崩溃,因为数据结构中没有数据。 (clearData()程序无关)
它不是随机的,因为我可以可靠地使它崩溃,但很难弄清楚它为什么会发生。因此,我已经包含了main.cpp和connection.cpp的全部内容。
我很缺乏经验,对于凌乱的代码和许多不良做法感到抱歉。它主要是OSX依赖的,可能适用于unix。希望能缩短它但它以简单的形式工作。
#include "connection.h"
#include "display.h"
#include "dataSort.h"
#include <sys/socket.h>
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include "pthread.h"
struct thread_data{
int threadNo;
int sockNo;
pthread_t threadC;
};
void *recData(void *data){//start server
clearData();
struct thread_data *threadData;
threadData = (struct thread_data*) data;
char buf[75];//35
int k;
while(1)
{
k = recv((*threadData).sockNo, buf, 75, 0);//35
if (k == -1)
{
printf("\ncannot read from client!\n");
break;
}
if (k == 0)
{
close((*threadData).sockNo);
int client = (*threadData).threadNo;
clearData();
printf("Client %d Disconnected\n",client); //print this here so program doesnt have to end when a client disconnects
sleep(2);
break;
}
if (k > 0){
//printf("%d\n",(*threadData).threadNo);
dataSort(buf,(*threadData).threadNo);
displayData();
}
//what now....
//break;
}
//close(threadData->sockNo);
return NULL;
}
void *acceptConn(void *data){
struct thread_data *threadData;
threadData = (struct thread_data*) data;
pthread_t thread;
void *status;
int sock_desc = (*threadData).sockNo;
struct sockaddr_in client;
memset(&client, 0, sizeof(client));
socklen_t len = sizeof(client);
int i = (*threadData).threadNo;
int j = (*threadData).sockNo;
sleep(1);
int temp_sock_desc= accept(3, (struct sockaddr*)&client, &len); //Wait for connection.
if (temp_sock_desc == -1){
//Accept connection didnt work.
}
(*threadData).sockNo = temp_sock_desc;
pthread_create(&thread, NULL, recData, (void *)threadData);
int rc = pthread_join(thread, &status);
if (rc) {
printf("Error waiting for thread\n");
}
//printf("Connection finished\n");
return NULL;
}
void *checkThreads(void *data){
struct thread_data *threadData;
threadData = (struct thread_data*) data;
void *status;
pthread_t thread[1];
pthread_t watchthread = (*threadData).threadC;
int i = (*threadData).threadNo;
int j = (*threadData).sockNo;
printf("Thread ID:%d\n",i);
printf("Socket No:%d\n",j);
pthread_join(watchthread, &status);
while (i < 3){
pthread_create(thread, NULL, acceptConn, (void *)threadData);
watchthread = (*threadData).threadC;
pthread_join(watchthread, &status);
}
return NULL;
}
int startHost()
{
printf("host created\n");
int sock_desc = socket(AF_INET, SOCK_STREAM, 0);
if (sock_desc == -1)
{
printf("cannot create socket!\n");
return 5; //Can't create socket
}
struct sockaddr_in server;
memset(&server, 0, sizeof(server));
server.sin_family = AF_INET;
server.sin_addr.s_addr = INADDR_ANY;
server.sin_port = htons(9025);
if (bind(sock_desc, (struct sockaddr*)&server, sizeof(server)) != 0)
{
close(sock_desc);
printf("cannot bind socket!\n");
sleep(2);
return 6; //no more connections available or socket not binded
}
if (listen(sock_desc, 10) != 0)
{
close(sock_desc);
printf("cannot listen on socket!\n");
return 5; //cant listen on socket (this error hasnt happened yet, just in case)
}
pthread_t thread[3];
pthread_t threadHelper[3];
struct thread_data threadID[3];//create a thread structure. threadID and socketID
for(int i=0; i < 3; i++ ){
threadID[i].threadNo = i;
threadID[i].sockNo = sock_desc;
pthread_create(&thread[i], NULL, acceptConn, (void *)&threadID[i]);
sleep(0.5);
threadID[i].threadC = thread[i];
pthread_create(&threadHelper[i], NULL, checkThreads, (void *)&threadID[i]);
}
pthread_exit(thread);
close(sock_desc);//socket closed
printf("server shutdown\n");
sleep(2);
return 0;
}
#include <iostream>
#include "connection.h"
#include <unistd.h>
struct main_thread{
int hasQuit;
};
void *runServer(void *data){
struct main_thread *mainData;
mainData = (struct main_thread*) data;
while ((*mainData).hasQuit == 0){
int debugCode;
int i = 0;
while (i == 0) {
debugCode = startHost();
switch (debugCode) {
case 2:
printf("\nClient disconnected.\n");
i = 1;
break;
case 3:
printf("Cannot accept client!\n");
break;
case 5:
printf("Socket Error. Please check network settings and status.\n");
i = 1;
break;
case 6:
break;
case 0:
printf("Server closed successfully\n");
break;
default:
break;
}
}
sleep(30);//prevents spamming the network if server cannot start.
//set so high because user is most likely at server and can manually
//quit and re-start. otherwise time is needed for port to free automatically.
}
return NULL;
}
void *readInput(void *data){
struct main_thread *mainData;
mainData = (struct main_thread*) data;
char input[5];
while (true){
scanf ("%s",input);
if ((strncmp(input, "quit", 4))||
(strncmp(input, "Quit", 4))||
(strncmp(input, "exit", 4))||
(strncmp(input, "Exit", 4)) == 0)
{
(*mainData).hasQuit = 1;
break;
}
}
return NULL;
}
int main(int argc, const char * argv[])
{
printf("Starting server on socket:%s\n",argv[1]);
printf("'Exit' or 'Quit' to close client\n");
pthread_t mainthread[2];
struct main_thread mainData;
void *Mstatus;
mainData.hasQuit = 0;
while (mainData.hasQuit == 0){
pthread_create(&mainthread[0], NULL, runServer, &mainData);
pthread_create(&mainthread[1], NULL, readInput,&mainData);
pthread_join(mainthread[1], &Mstatus);
}
printf("Server exiting...\n");
return 0;
}
#include <iostream>
#include "connection.h"
#include <unistd.h>
void runServer(){
int debugCode;
int i = 0;
while (i == 0) {
debugCode = startHost();
switch (debugCode) {
case 2:
printf("\nClient disconnected.\n");
i = 1;
break;
case 3:
printf("Cannot accept client!\n");
break;
case 5:
printf("Socket Error. Please check network settings and status.\n");
i = 1;
break;
case 6:
break;
case 0:
printf("Server closed successfully\n");
break;
default:
break;
}
}
}
int main(int argc, const char * argv[])
{
runServer();
return 0;
}