I have next trouble: after receiving data from sockets, server app generates segfault and shutdown. Code of client and server side are below.
server:
#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; }
Client:
#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; }
In other words, client connected successfully. But after sending message, server generate segm fault error. What went wrong?
Advertisement
Answer
When running the code it seg faults at:
cout<< package.nick << " : " << package.buff << endl;
Package is a struct with two members nick and buff. Then you read the socket with the size of PACKAGE struct which is size 16. I guess this is not really what you want. Maybe you could specify nick and buff as fixed length char arrays.
struct PACKAGE{ char nick[1024]; char buff[1024];};