2015-06-24 40 views
-1

我有下一个麻烦:从套接字接收数据后,服务器应用程序生成段错误和关机。下面是客户端和服务器端的代码。SEGFAULT从套接字接收后

服务器:

#include <iostream> 
#include <sys/socket.h> 
#include <netdb.h> 
#include <vector> 
#include <arpa/inet.h> 
#include <string.h> 
#include <algorithm> 
#include <unistd.h> 
#include <pthread.h> 

using namespace std; 

static const int PORT= 20202; 
static const string HOST = "127.0.0.1"; 
static const int MAX_CLIENTS = 10; 


struct THREADINFO { 
pthread_t thread_ID; 
int sockfd; 
string nick; 
}; 

struct PACKAGE{ 
    string nick; 
    string buff; 
}; 


int compare(THREADINFO *a, THREADINFO *b) { 
    return a->sockfd - b->sockfd; 
} 



int sockfd, newfd; 
THREADINFO thread_info[10]; 
vector<THREADINFO> client_list; 
pthread_mutex_t clientlist_mutex; 
void *client_handler(void *fd); 
int main(){ 
    int err_ret, sin_size; 
    sockaddr_in serv_addr, client_addr; 
    pthread_mutex_init(&clientlist_mutex, NULL); 

    /* open a socket */ 
    if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) { 
     err_ret = errno; 
     cerr << "socket() failed..." <<endl; 
     return err_ret; 
    } 

    serv_addr.sin_family = AF_INET; 
    serv_addr.sin_port = htons(PORT); 
    serv_addr.sin_addr.s_addr = inet_addr(HOST.c_str()); 
    memset(&(serv_addr.sin_zero), 0, 8); 

    if(bind(sockfd, (sockaddr *)&serv_addr, sizeof(sockaddr)) == -1) { 
     err_ret = errno; 
     cerr << "bind() failed..." <<endl; 
     return err_ret; 
    } 

    if(listen(sockfd, MAX_CLIENTS) == -1) { 
     err_ret = errno; 
     cerr << "listen() failed...." <<endl; 

     return err_ret; 
    } 

    cout << "Starting socket listener.." << endl; 
    while(1) { 
     sin_size = sizeof(sockaddr_in); 
     if((newfd = accept(sockfd, (sockaddr *)&client_addr, (socklen_t*)&sin_size)) == -1) { 
      err_ret = errno; 
      cerr << "accept() failed..." <<endl; 
      return err_ret; 
     } 
     else { 
      if(client_list.size() == MAX_CLIENTS) { 
       cerr << "Connection full, request rejected..." <<endl; 
       continue; 
      } 
      cout << "Connection requested received"<<endl; 
      THREADINFO threadinfo; 
      threadinfo.sockfd = newfd; 
      threadinfo.nick = "Anonymous"; 
      pthread_mutex_lock(&clientlist_mutex); 
      client_list.push_back(threadinfo); 
      pthread_mutex_unlock(&clientlist_mutex); 
      pthread_create(&threadinfo.thread_ID, NULL, client_handler, (void *)&threadinfo); 
     } 
    } 
    return 0; 
} 

vector<THREADINFO>::iterator findThread(vector<THREADINFO>& vector1,THREADINFO& threadInfo){ 

    for (auto item = vector1.begin();item != vector1.end();++item){ 
     if (compare(&(*item),&threadInfo) == 0){ 
      return item; 
     } 
    } 
} 

void *client_handler(void *fd) { 
    THREADINFO threadinfo = *(THREADINFO *)fd; 
    PACKAGE package; 
     int bytes, sent; 
     while(1) { 
     bytes = recv(threadinfo.sockfd, (void *)&package, sizeof(PACKAGE), 0); 
     if(!bytes) { 
      cerr << "Connection lost from " << threadinfo.nick; 
      pthread_mutex_lock(&clientlist_mutex); 
      if (!client_list.empty()) { 
       client_list.erase(findThread(client_list,threadinfo)); 
      } 
      pthread_mutex_unlock(&clientlist_mutex); 
      break; 
     } 
      cout<< package.nick << " : " << package.buff << endl; 
      pthread_mutex_lock(&clientlist_mutex); 
       for (size_t i=0;i<client_list.size();i++){ 
       PACKAGE spacket; 
       if(!compare(&client_list[i], &threadinfo)) continue; 
        spacket.nick = package.nick; 
        spacket.buff = package.buff; 
        sent = send(client_list[i].sockfd, (void *)&spacket, sizeof(PACKAGE), 0); 

       } 
      pthread_mutex_unlock(&clientlist_mutex); 


     if(package.buff.compare("exit") == 0) { 
      cout << "Client is disconnected" << endl; 

      pthread_mutex_lock(&clientlist_mutex); 
      if (!client_list.empty()) { 
       client_list.erase(findThread(client_list,threadinfo)); 
      } 
      pthread_mutex_unlock(&clientlist_mutex); 
      break; 
     } 
     else { 
      cerr << "Garbage data from " << threadinfo.sockfd <<" " <<threadinfo.nick; 
     } 
    } 

    /* clean up */ 
    close(threadinfo.sockfd); 

    return NULL; 
} 

客户:

#include <iostream> 
#include <netdb.h> 
#include <pthread.h> 
#include <sys/socket.h> 
#include <sys/types.h> 
#include <arpa/inet.h> 
#include <string.h> 
#include <unistd.h> 

using namespace std; 

static const int PORT = 20202; 
static const string HOST = "127.0.0.1"; 
void *receiver(void *param); 

struct PackageInfo{ 
    string nick; 
    string buff; 
}; 

struct User{ 
    int sockfd; 
    string nick; 
}; 
struct ThreadInfo{ 
    pthread_t thread; 
    int sockfd; 

}; 


int isDisconnected,sockfd; 


int connectWithServer(){ 
    int newfd, err_ret; 
    sockaddr_in serv_addr; 
    hostent *to; 

    if((to = gethostbyname(HOST.c_str()))==NULL) { 
     err_ret = errno; 
     cerr<<"HOST ERROR" << endl; 
     return err_ret; 
    } 

    if((newfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) { 
     err_ret = errno; 
     cerr<<"SOCKET ERROR" << endl; 
     return err_ret; 
    } 

    serv_addr.sin_family = AF_INET; 
    serv_addr.sin_port = htons(PORT); 
    serv_addr.sin_addr = *((in_addr *)to->h_addr); 
    memset(&(serv_addr.sin_zero), 0, 8); 

    if(connect(newfd, (sockaddr *)&serv_addr, sizeof(sockaddr)) == -1) { 
     err_ret = errno; 
     cerr << "CONNECT ERROR"<<endl; 
     return err_ret; 
    } 
    else { 
     cout << "CONNECTED!"<<endl; 
     return newfd; 
    } 
} 

void login(User* client){ 
    if(isDisconnected){ 
     cerr << "You'are disconnected"; 
     return; 
    } 
    sockfd = connectWithServer(); 
    if(sockfd >= 0) { 
     isDisconnected = 1; 
     client->sockfd = sockfd; 
     cout << "Logged in as " << client->nick << endl; 
     ThreadInfo threadinfo; 
     pthread_create(&threadinfo.thread, NULL, receiver, (void *)&threadinfo); 

    } 
    else { 
     cerr << "Connection rejected..." << endl; 
    } 


} 

void *receiver(void *param){ 
    int recvd; 
    PackageInfo package; 

    cout << "Waiting server..." << endl; 

    while (isDisconnected){ 
     recvd = recv(sockfd, (void *)&package, sizeof(PackageInfo), 0); 
     if (!recvd){ 
      cerr << "Connection lost"; 
      isDisconnected = 0; 
      close(sockfd); 
      break; 
     } 
     if(recvd > 0){ 
      cout << package.nick << " : " << package.buff<<endl; 
     } 
    } 
    return NULL; 

} 

void sentToServer(User* client,string& message){ 
    int sent; 
    PackageInfo package; 

    if(!isDisconnected) { 
     cerr << "\"You are not connected..." << endl; 
     return; 
    } 

    package.nick = client->nick; 
    package.buff = message; 


    sent = send(sockfd, (void *)&package, sizeof(PackageInfo), 0); 

} 

int main() { 
    User user; 
    cout << "Enter nickname: "; 
    getline(cin,user.nick); 
    login(&user); 
     string message; 
    while (cin >> message){ 
     sentToServer(&user,message); 
    } 
    return 0; 
} 

换句话说,客户端成功地连接。但是在发送消息之后,服务器生成segm错误错误。什么地方出了错?

回答

1

当它运行在赛格故障代码:

cout<< package.nick << " : " << package.buff << endl; 

套餐是两个成员尼克和BUFF一个结构。然后你读取大小为16的PACKAGE结构的套接字。我想这不是你想要的。也许你可以指定nick和buff作为固定长度的char数组。

struct PACKAGE{ char nick[1024]; char buff[1024];}; 
+0

真的。谢谢。但我不明白,为什么它不工作与STD ::字符串? –

+0

您正在读取的是PACKAGE大小的字节数。包的大小是在编译时定义的,因此您只需读取16个字节,而不是来自客户端的完整消息。 –

0

您没有使用任何数据初始化threadinfo.thread_ID。你应该定义新pthread_t,然后把它作为参数传递给pthread_create()