- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
这是一个简单的客户端服务器系统。服务器使用select来处理不同的客户端请求。但问题是:当我关闭客户端时,服务器将出现段错误。我不知道该如何处理这种情况。感谢您的帮助。
客户端:
#include <stdio.h>
#include <iostream>
#include <stdlib.h>
#include <queue>
#include <cstdlib>
#include <string.h>
#include <mutex>
#include <thread>
#include <pthread.h>
#include <sys/socket.h> /* for socket(), connect(), send(), and recv() */
#include <arpa/inet.h> /* for sockaddr_in and inet_addr() */
#include <stdlib.h> /* for atoi() and exit() */
#include <string.h> /* for memset() */
#include <unistd.h> /* for close() */
#include <ctype.h>
#define SIZESTACKSPACE 1000000;
#define RCVBUFSIZE 32 /* Size of receive buffer */
using namespace std;
void *sendRequest(void *);
void *receiveRequest(void *);
//#define TEMPPORTNO "40868";
//#define IP1 "10.10.154.41";
//#define IP1 "192.168.37.166";
int sock; /* Socket descriptor */
bool running1 = true, running2 = true;
//queue1 is used for sending message
//queue2 is used by recieve to display message
queue<char*> queue1, queue2;
//create two mutex for two queue
pthread_mutex_t mutex1 = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_t mutex2 = PTHREAD_MUTEX_INITIALIZER;
//create conditional variables
pthread_cond_t cond1 = PTHREAD_COND_INITIALIZER;
pthread_cond_t cond2 = PTHREAD_COND_INITIALIZER;
pthread_attr_t attr;
int main(void){
pthread_t thread2, thread1;
int rc2, rc1;
size_t stacksize;
//initialize attributes
pthread_attr_init(&attr);
pthread_attr_getstacksize (&attr, &stacksize);
stacksize = sizeof(double)*1000+SIZESTACKSPACE;
pthread_attr_setstacksize(&attr, stacksize);
//create thread1, with function sendRequest()
rc1 = pthread_create(&thread1, &attr, sendRequest, NULL);
if(rc1){
cout<<" ERROR; return code from pthread_create() is " << rc1;
exit(-1);
}
//create thread2, with the function recieveRequest()
rc2 = pthread_create(&thread2, &attr, receiveRequest, NULL);
if(rc2){
cout<<" ERROR; return code from pthread_create() is " << rc2;
exit(-1);
}
int chunksize = 4; /* use BUFSIZ-1 for (probably) more efficient program */
char *s;
char *temp;
int buffersize;
int nPos;
char c;
char *str;
while(1){
buffersize = chunksize+1;
s = (char*) malloc(buffersize); /* get the first chunk */
if (s == NULL) {
printf("Can't allocate %d bytes\n", buffersize);
exit(1);
}
if((c=getchar()) != '\n' && c != EOF){
nPos = 1;
s[0] = c;
while((c=getchar()) != '\n' && c != EOF){
s[nPos] = c;
if(nPos>=buffersize){
buffersize += chunksize;
temp = (char*)realloc(s, buffersize);
if (temp == NULL) {
printf("Can't realloc %d bytes\n", chunksize);
free(s); /* clean up the previously allocated stuff */
s = NULL;
exit(1);
}
s=temp;
}
nPos++;
}
int k, j;
/*The last character is null*/
//nPos is the length of the string, aside of the null character
s[nPos] = '\0';
//to store the new string, allocation
str = (char*) malloc(nPos+6);
j = nPos;
//each byte contains a value of the number
k = 3;
while(k>=0){
str[k] = nPos % 10;
nPos = nPos/10;
k--;
}
str[4] = '\0';
k = 0;
while(k<=j){
str[k+5] = s[k];
k++;
}
str[k+5] = '\0';
free(s);
//add mutex here
pthread_mutex_lock(&mutex1);
queue1.push(str);
//signal sendRequest
if(!queue1.empty())
pthread_cond_signal(&cond1);
pthread_mutex_unlock(&mutex1);
//signal recvRequest
pthread_mutex_lock(&mutex2);
queue2.push(str);
if(!queue2.empty())
pthread_cond_signal(&cond2);
pthread_mutex_unlock(&mutex2);
}else if(c==EOF){
break;
}
}
//wait for thread 2
while(!queue2.empty());
//signal for threads
close(sock);
/* Clean up and exit */
pthread_attr_destroy(&attr);
pthread_exit(NULL);
pthread_mutex_destroy(&mutex1);
pthread_mutex_destroy(&mutex2);
pthread_cond_destroy(&cond1);
pthread_cond_destroy(&cond2);
return 0;
}
void *sendRequest(void *){
struct sockaddr_in echoServAddr; /* Echo server address */
unsigned short servPort; /* server port */
char* servIP; /* Server IP address (dotted quad) */
char* echoString; /* String to send to echo server */
unsigned int stringLen;
char* tempPort;
//fetch environment variables from the system
servIP = getenv ("SERVER_ADDRESS");
tempPort = getenv("SERVER_PORT");
// servIP = IP1;
// tempPort = TEMPPORTNO;
if(strlen(servIP) == 0 || strlen(tempPort) == 0){
perror("DOES NOT SET ENVIRONMENT VARIABLES FOR SERVER_ADDRESS OR SERVER_PORT\n");
exit(-1);
}
servPort = atoi(tempPort);
/* Create a reliable, stream socket using TCP */
if ((sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0){
printf("socket() failed\n");
exit(1);
}
/* Construct the server address structure */
memset(&echoServAddr, 0, sizeof(echoServAddr)); /* Zero out structure */
echoServAddr.sin_family = AF_INET; /* Internet address family */
echoServAddr.sin_addr.s_addr = inet_addr(servIP); /* Server IP address */
echoServAddr.sin_port = htons(servPort); /* Server port */
/* Establish the connection to the echo server */
if (connect(sock, (struct sockaddr *) &echoServAddr, sizeof(echoServAddr)) < 0){
perror("connect() failed\n");
exit(1);
}
pthread_mutex_lock(&mutex1);
while(true){
pthread_cond_wait(&cond1, &mutex1);
echoString = queue1.front();
queue1.pop();
pthread_mutex_unlock(&mutex2);
//send a request to the server
//determine the length that is going to be sent
stringLen = 5;
while(echoString[stringLen])
stringLen++;
/* Send the string to the server */
if (send(sock, echoString, stringLen, 0) != (int)stringLen){
perror("send() sent a different number of bytes than expected\n");
exit(1);
}
sleep(2);//sleep for 2 seconds
}
return (void *) 0;
}
void *receiveRequest(void *){
char* temp;
char *echoBuffer; /* Buffer for echo string */
unsigned int echoStringLen; /* Length of string to echo */
unsigned int bytesRcvd; /* Bytes read in single recv()]*/
char *partTemp;
unsigned int stringLen;
pthread_mutex_lock(&mutex2);
while(true){
//get the toppest value from the queue
pthread_cond_wait(&cond2, &mutex2);
temp = queue2.front();
pthread_mutex_unlock(&mutex2);
//get the length from the queue
//cp the first four bytes
int k = 0;
stringLen = 0;
while(k<4){
stringLen = stringLen * 10 + temp[k];
k++;
}
//wait for response
echoBuffer = (char *)malloc(5);
if((bytesRcvd = recv(sock, echoBuffer,5, 0)) <= 0){
printf("recv() failed or connection closed prematurely\n");
exit(1);
}
//totalBytesRcvd += bytesRcvd;
//get the length of the string recv
k=0;
echoStringLen = 0;
while(k<4){
echoStringLen = echoStringLen * 10 + echoBuffer[k];
k++;
}
echoBuffer = (char *)realloc(echoBuffer, echoStringLen + 1);
//recive the rest of the string, which is a length of echoStringLen+1
bytesRcvd = recv(sock, echoBuffer, echoStringLen+1, 0);
echoBuffer[echoStringLen] = '\0';
//escape the first 5 bytes for the printing
partTemp = temp;
k=0;
while(k<5){
partTemp ++;
k++;
}
printf("%s\nServer: %s \n", partTemp, echoBuffer);
free(echoBuffer);
//pop the toppest value from the queue
//this is useful for closing the threads
//it can ensure all allocations are freed
pthread_mutex_lock(&mutex2);
queue2.pop();
free(temp);
pthread_mutex_unlock(&mutex2);
}
return (void *) 0;
}
服务器端:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <ifaddrs.h>
#define PORT 0
#define MAXPENDING 5
int main(){
struct sockaddr_in serverAddress, clientAddress; // These stores the network settings
socklen_t serverAddressLength = sizeof(serverAddress), clientAddressLength = sizeof(clientAddress);
int serverSocketID, clientSocketID;
if ((serverSocketID = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) {
perror("socket() failed");
exit(1);
}
// Specifying preference for IP address and port number lookup
memset(&serverAddress, 0, sizeof(serverAddress)); // Initialize memory for
serverAddress.sin_family = AF_INET;
serverAddress.sin_addr.s_addr = htonl(INADDR_ANY);
serverAddress.sin_port = htons(PORT);
if (bind(serverSocketID, (struct sockaddr *) &serverAddress, serverAddressLength) != 0) {
perror("bind() failed");
close(serverSocketID);
exit(1);
}
// Server starts to listen
if (listen(serverSocketID, MAXPENDING) == -1) {
perror("listen() failed");
close(serverSocketID);
exit(1);
}
//The following code is to obtain IP address from ifaddr info from Linux
getsockname(serverSocketID, (struct sockaddr*) &serverAddress, &serverAddressLength);
struct ifaddrs * ifAddrStruct=NULL;
struct ifaddrs * ifa=NULL;
void * tmpAddrPtr=NULL;
getifaddrs(&ifAddrStruct);
for (ifa = ifAddrStruct; ifa != NULL; ifa = ifa->ifa_next) {
if (ifa ->ifa_addr->sa_family==AF_INET) { // check it is IP4
// is a valid IP4 Address
tmpAddrPtr=&((struct sockaddr_in *)ifa->ifa_addr)->sin_addr;
char addressBuffer[INET_ADDRSTRLEN];
inet_ntop(AF_INET, tmpAddrPtr, addressBuffer, INET_ADDRSTRLEN);
if(ifa->ifa_name[0] == 'e' ){
printf("SERVER_ADDRESS %s\nSERVER_PORT %d\n", addressBuffer, (int) ntohs(serverAddress.sin_port));
break;
}
} else if (ifa->ifa_addr->sa_family==AF_INET6) { // check it is IP6
// is a valid IP6 Address
tmpAddrPtr=&((struct sockaddr_in6 *)ifa->ifa_addr)->sin6_addr;
char addressBuffer[INET6_ADDRSTRLEN];
inet_ntop(AF_INET6, tmpAddrPtr, addressBuffer, INET6_ADDRSTRLEN);
if(ifa->ifa_name[0] == 'e' ){
printf("SERVER_ADDRESS %s\nSERVER_PORT %d\n", addressBuffer, (int) ntohs(serverAddress.sin_port));
break;
}
}
}
if (ifAddrStruct!=NULL) freeifaddrs(ifAddrStruct);
// Select attributes
int largestFileDescriptorIndex = serverSocketID;
// We will add clients to the master list, select will use a worker copy of our master list
fd_set master, worker;
//initialize the file descriptor list
FD_ZERO(&master);
FD_ZERO(&worker);
FD_SET(serverSocketID, &master);
// Add keyboard to allow control over server
FD_SET(STDIN_FILENO, &master);
// Specify how long to block and wait for a client to do something
struct timeval fileDescriptorWaitTime;
// Wait for 1 second to check if there is data coming in
fileDescriptorWaitTime.tv_sec = 1;
fileDescriptorWaitTime.tv_usec = 0;
int running = 1, i;
while(running) { // This is the big red switch that makes the server run
worker = master; // Resets the select list
if (select(largestFileDescriptorIndex + 1, &worker, NULL, NULL, &fileDescriptorWaitTime) == -1) {
perror("select() failed");
close(serverSocketID);
exit(1);
}
// Loop through the state of all file descriptors
for (i = 0; i <= largestFileDescriptorIndex; i++) {
// Check if any file descriptor changed state
if (FD_ISSET(i, &worker)) {
// A new client is trying to connect
if (i == serverSocketID) {
// Client connect successfully
if ((clientSocketID = accept(serverSocketID,
(struct sockaddr*) &clientAddress, &clientAddressLength)) != -1) {
// Register client into master list
FD_SET(clientSocketID, &master);
if (clientSocketID > largestFileDescriptorIndex) {
// Update length of list to loop
largestFileDescriptorIndex = clientSocketID;
}
}
}
else if (i == STDIN_FILENO) { // Check keyboard input
fprintf(stdout, "Server is Shutting down\n");
getchar();
running = 0;
continue;
}else
{
char *echoBuffer; /* Buffer for echo string */
int recvMsgSize; /* Size of received message */
int j;
echoBuffer = (char *)malloc(5);
/* Receive message from client, get the first 5 bytes first to know the length of the string*/
if ((recvMsgSize = recv(clientSocketID, echoBuffer, 5, 0)) < 0){
perror("recv() failed");
close(clientSocketID);
FD_CLR(clientSocketID, &master);
}
int stringLen=0, k = 0;//the length of the string
/*convert the char * into an int*/
while(k<4){
stringLen = stringLen*10 + (int)echoBuffer[k];
k++;
}
char *str; // store the string
//string size + 4 bytes + '\0'+strlen(string)+'\0'
str = (char *)malloc(stringLen + 6);
//put the first 5 bytes into the echo string
k = 0;
while(k<5){
str[k] = echoBuffer[k];
k++;
}
free(echoBuffer);
//recieve string of a length of stringLen+1, which is char num + '\0'
echoBuffer = (char *)malloc(stringLen+1);
if ((recvMsgSize = recv(clientSocketID, echoBuffer, stringLen+1, 0)) < 0){
perror("recv() failed");
close(clientSocketID);
FD_CLR(clientSocketID, &master);
}
//set the last char to be null
echoBuffer[stringLen]='\0';
printf("%s\n", echoBuffer);
//deal with the data here
if(echoBuffer[0] <= 'z' && echoBuffer[0]>='a')
echoBuffer[0] = echoBuffer[0] + 'A'-'a';
//operations on data except the first one
for( j = 1; j<stringLen; j++)
{
if(echoBuffer[j]<='z' && echoBuffer[j]>='a' && echoBuffer[j-1] == ' ')
echoBuffer[j] = echoBuffer[j] + 'A'-'a';
else if(echoBuffer[j]<='Z' && echoBuffer[j]>='A' && echoBuffer[j-1] != ' ')
echoBuffer[j] = echoBuffer[j] + 'a'-'A';
}
//store the data into str
k= 0;
while(k<=stringLen){
str[k+5] = echoBuffer[k];
k++;
}
str[stringLen+5] = '\0';
free(echoBuffer);
recvMsgSize = stringLen+6;
/* Send received string */
/* Echo message back to client */
if (send(clientSocketID, str, recvMsgSize, 0) != recvMsgSize){
perror("send() failed");
close(clientSocketID);
FD_CLR(clientSocketID, &master);
}
free(str);
}//operations on the data finishes
}//if the client socket descriptor is in the list
}//loop through all the file descriptors
}//busy waiting
close(serverSocketID);
return 0;
}
最佳答案
当客户端断开连接时,客户端的套接字将选择为读就绪状态,然后该套接字上的所有后续尝试将返回 0,以指示 EOF。请注意,这种情况是 recv() 返回 0 的唯一一次。看起来您的代码在这种情况下期望 recv() 返回 -1,因此它无法正确处理这种情况。
此外,您似乎尝试在 free() 后使用 echoBuffer,这是未定义的行为,应该避免。 (事实上,为什么要使用 malloc() 和 free() 呢?只需在堆栈上声明一个足够大的 echoBuffer,您就不必担心何时 free() 它)
关于c++ - 客户端断开连接时 TCP 套接字选择服务器段错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22561960/
#include using namespace std; class C{ private: int value; public: C(){ value = 0;
这个问题已经有答案了: What is the difference between char a[] = ?string?; and char *p = ?string?;? (8 个回答) 已关闭
关闭。此题需要details or clarity 。目前不接受答案。 想要改进这个问题吗?通过 editing this post 添加详细信息并澄清问题. 已关闭 7 年前。 此帖子已于 8 个月
除了调试之外,是否有任何针对 c、c++ 或 c# 的测试工具,其工作原理类似于将独立函数复制粘贴到某个文本框,然后在其他文本框中输入参数? 最佳答案 也许您会考虑单元测试。我推荐你谷歌测试和谷歌模拟
我想在第二台显示器中移动一个窗口 (HWND)。问题是我尝试了很多方法,例如将分辨率加倍或输入负值,但它永远无法将窗口放在我的第二台显示器上。 关于如何在 C/C++/c# 中执行此操作的任何线索 最
我正在寻找 C/C++/C## 中不同类型 DES 的现有实现。我的运行平台是Windows XP/Vista/7。 我正在尝试编写一个 C# 程序,它将使用 DES 算法进行加密和解密。我需要一些实
很难说出这里要问什么。这个问题模棱两可、含糊不清、不完整、过于宽泛或夸夸其谈,无法以目前的形式得到合理的回答。如需帮助澄清此问题以便重新打开,visit the help center . 关闭 1
有没有办法强制将另一个 窗口置于顶部? 不是应用程序的窗口,而是另一个已经在系统上运行的窗口。 (Windows, C/C++/C#) 最佳答案 SetWindowPos(that_window_ha
假设您可以在 C/C++ 或 Csharp 之间做出选择,并且您打算在 Windows 和 Linux 服务器上运行同一服务器的多个实例,那么构建套接字服务器应用程序的最明智选择是什么? 最佳答案 如
你们能告诉我它们之间的区别吗? 顺便问一下,有什么叫C++库或C库的吗? 最佳答案 C++ 标准库 和 C 标准库 是 C++ 和 C 标准定义的库,提供给 C++ 和 C 程序使用。那是那些词的共同
下面的测试代码,我将输出信息放在注释中。我使用的是 gcc 4.8.5 和 Centos 7.2。 #include #include class C { public:
很难说出这里问的是什么。这个问题是含糊的、模糊的、不完整的、过于宽泛的或修辞性的,无法以目前的形式得到合理的回答。如需帮助澄清此问题以便重新打开它,visit the help center 。 已关
我的客户将使用名为 annoucement 的结构/类与客户通信。我想我会用 C++ 编写服务器。会有很多不同的类继承annoucement。我的问题是通过网络将这些类发送给客户端 我想也许我应该使用
我在 C# 中有以下函数: public Matrix ConcatDescriptors(IList> descriptors) { int cols = descriptors[0].Co
我有一个项目要编写一个函数来对某些数据执行某些操作。我可以用 C/C++ 编写代码,但我不想与雇主共享该函数的代码。相反,我只想让他有权在他自己的代码中调用该函数。是否可以?我想到了这两种方法 - 在
我使用的是编写糟糕的第 3 方 (C/C++) Api。我从托管代码(C++/CLI)中使用它。有时会出现“访问冲突错误”。这使整个应用程序崩溃。我知道我无法处理这些错误[如果指针访问非法内存位置等,
关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。 我们不允许提问寻求书籍、工具、软件库等的推荐。您可以编辑问题,以便用事实和引用来回答。 关闭 7 年前。
已关闭。此问题不符合Stack Overflow guidelines 。目前不接受答案。 要求我们推荐或查找工具、库或最喜欢的场外资源的问题对于 Stack Overflow 来说是偏离主题的,因为
我有一些 C 代码,将使用 P/Invoke 从 C# 调用。我正在尝试为这个 C 函数定义一个 C# 等效项。 SomeData* DoSomething(); struct SomeData {
这个问题已经有答案了: Why are these constructs using pre and post-increment undefined behavior? (14 个回答) 已关闭 6
我是一名优秀的程序员,十分优秀!