Ich habe einen Client und Server eingerichtet, um miteinander zu sprechen. Aber jedes Mal, wenn ich versuche, zurück zum Client zu sprechen, scheint der Socket getrennt zu sein. Ein großer Teil des Codes ist aus einem Socket-Tutorial über yolinux angepasst. Außerdem laufe ich das remote über ssh.Socket konsequent trennen C++
Auftraggeber:
#include <cerrno>
#include <sys/types.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <sys/socket.h>
#include <netdb.h>
#include <sys/select.h>
#include <sys/time.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <errno.h>
#include <iostream>
#include <cstdlib>
#include <stdlib.h>
#include <strings.h>
#include <string.h>
#include <string>
#include <sstream>
using namespace std;
main(int argc, char *argv[])
{
if (argc != 3) {
cout << "exiting\n";
exit(EXIT_FAILURE);
}
struct sockaddr_in remoteSocketInfo;
struct hostent *hPtr;
int socketHandle;
char *remoteHost = argv[1];
int portNumber = atoi(argv[2]);
cout << "Welcome!\n";
// create socket
if ((socketHandle = socket(AF_INET, SOCK_STREAM, IPPROTO_IP)) < 0)
{
cout << "Socket creation failed.\n";
close(socketHandle);
exit(EXIT_FAILURE);
}
cout << "Socket created!\n";
bzero(&remoteSocketInfo, sizeof(sockaddr_in)); // Clear structure memory
if ((hPtr = gethostbyname(remoteHost)) == NULL)
{
cerr << "System DN name resolution not configured properly.\n";
cerr << "Error number: " << ECONNREFUSED << endl;
exit(EXIT_FAILURE);
}
// Load system information for remote socket server into socket data structures
memcpy((char*)&remoteSocketInfo.sin_addr, hPtr->h_addr, hPtr->h_length);
remoteSocketInfo.sin_family = AF_INET;
remoteSocketInfo.sin_port = htons((u_short)portNumber); // set port number
if (connect(socketHandle, (struct sockaddr *)&remoteSocketInfo, sizeof(sockaddr_in)) < 0) {
cout << "connection failed\n";
close(socketHandle);
exit(EXIT_FAILURE);
}
cout << "Connected!\n";
string input;
int message;
while (1) {
cout << "Please indicate rotation amount:";
cin >> input;
if (input == "exit") {
close(socketHandle);
break;
}
char buf[input.length()+1];
const char *conv_input = input.c_str();
strcpy(buf, conv_input);
int bytes_sent = 0;
if ((bytes_sent = send(socketHandle, buf, strlen(buf)+1, 0)) < 0) {
char buffer[256];
char * errorMessage = strerror_r(errno, buffer, 256);
cout << errorMessage << endl;
close(socketHandle);
exit(EXIT_FAILURE);
}
cout << "bytes sent: " << bytes_sent << endl;
int rc;
char buf2[input.length()+1];
rc = recv(socketHandle, buf2, strlen(buf)+1, 0);
buf[rc] = (char)NULL; // Null terminate string
cout << "received: " << buf2 << endl;
cout << "bytes received: " << rc << endl;
}
close(socketHandle);
}
Server:
#include <iostream>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <stdlib.h>
#include <strings.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <cstring>
#define MAXHOSTNAME 256
using namespace std;
main(int argc, char *argv[])
{
if (argc != 2) {
cout << "not enough arguments, ex: ./CaesarCipherServer 9876\n";
exit(EXIT_FAILURE);
}
struct sockaddr_in socketInfo;
char sysHost[MAXHOSTNAME+1]; // Hostname of this computer we're running on
struct hostent *hPtr;
int portNumber = atoi(argv[1]);
int sock;
bzero(&socketInfo, sizeof(sockaddr_in)); // Clear structure memory
// Get system information
gethostname(sysHost, MAXHOSTNAME); // Get this computer's hostname
if ((hPtr = gethostbyname(sysHost)) == NULL)
{
cerr << "System hostname misconfigured." << endl;
exit(EXIT_FAILURE);
}
if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0)
{
close(sock);
exit(EXIT_FAILURE);
}
// Load system info into socket data structures
socketInfo.sin_family = AF_INET;
socketInfo.sin_addr.s_addr = htonl(INADDR_ANY); // Use any addr available
socketInfo.sin_port = htons(portNumber); // Set port number
// Bind the socket to a local socket address
if (bind(sock, (struct sockaddr *) &socketInfo, sizeof(socketInfo)) < 0)
{
close(sock);
perror("bind");
exit(EXIT_FAILURE);
}
cout << "listening for initial connection \n";
listen(sock, 1);
int sockConn;
if ((sockConn = accept(sock, NULL, NULL)) < 0)
{
exit(EXIT_FAILURE);
} else {
cout << "connection accepted!\n";
}
int rc = 0;
char buf[512];
cout << "about to receive message... \n";
// rc is number of chars returned
rc = recv(sockConn, buf, 512, 0);
buf[rc] = (char)NULL; // Null terminate string
cout << "received: " << buf << endl;
cout << "rc: " << rc << endl;
int bytes_sent;
if ((bytes_sent = send(sock, buf, rc, MSG_NOSIGNAL)) < 0) {
cout << "error sending\n";
close(sock);
exit(EXIT_FAILURE);
}
cout << "bytes sent: " << bytes_sent << endl;
close(sock);
}
Client-Ausgabe:
./CaesarCipherClient cs-ssh 9876
Welcome!
Socket created!
socket handle : 3
Connected!
Please indicate rotation amount:5
bytes sent: 2
received:
bytes received: 0
Please indicate rotation amount:
Server Output:
./CaesarCipherServer 9876
listening for initial connection
connection accepted!
about to receive message...
received: 5
rc: 2
error sending
Wenn das Flag MSG_NOSIGNAL nicht angegeben ist, stürzt der Server bei send() ab, was bedeutet, dass der Socket am anderen Ende getrennt wurde. Warum sollte der Socket nach einem send()/recv() -Paar immer wieder getrennt werden?
Ich entschuldige mich für schlechte Lesbarkeit/Stil/reine Dummheit in meinem Beitrag.