我有一个客户端和服务器设置为彼此交谈。但每次我尝试回应客户端时套接字似乎已断开连接。大部分代码都是根据yolinux的套接字教程改编的。另外,我通过ssh远程运行它。
#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);
}
#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);
}
./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:
./CaesarCipherServer 9876
listening for initial connection
connection accepted!
about to receive message...
received: 5
rc: 2
error sending
如果未指定MSG_NOSIGNAL标志,则服务器在send()处崩溃,这意味着套接字已在另一端断开连接。为什么套接字在send()/ recv()对之后始终断开连接?
对于我提交的任何可读性/风格/纯粹的愚蠢,我道歉。
答案 0 :(得分:6)
在您的服务器中,您正在使用:
if ((bytes_sent = send(sock, buf, rc, MSG_NOSIGNAL)) < 0) {
cout << "error sending\n";
close(sock);
exit(EXIT_FAILURE);
}
这里,sock
是侦听套接字,而不是接受的客户端套接字。您需要将sock
替换为sockCon
(您在recv()
函数调用中使用的那个,这是有效的。)