我有下一个麻烦:从套接字接收数据后,服务器应用程序会生成段错误和关闭。客户端和服务器端的代码如下。
服务器:
#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错误。什么地方出了错?
答案 0 :(得分:1)
运行代码时,它会出现以下错误:
struct PACKAGE{ char nick[1024]; char buff[1024];};
Package是一个包含两个成员nick和buff的结构。然后你读取大小为16的PACKAGE结构的套接字。我想这不是你想要的。也许你可以将nick和buff指定为固定长度的char数组。
jekyll serve
答案 1 :(得分:0)
您没有使用任何数据初始化threadinfo.thread_ID
。您应该定义新的pthread_t
,然后将其作为参数传递给pthread_create()