C Linux套接字:第二次读取()在本地主机上失败
我有一个服务器,它确认一个命令,然后发送数据。它与命令行配合良好:C Linux套接字:第二次读取()在本地主机上失败,c,linux,sockets,C,Linux,Sockets,我有一个服务器,它确认一个命令,然后发送数据。它与命令行配合良好:echo“show version”| nc-q1 127.0.0.1 5000给出: Command received: show version Beta 我有一个客户端,它的行为应该与命令行测试完全相同,但是它挂起在第二个read()调用上,除非我在不同的服务器上运行它。我对unix域套接字也有同样的问题,只是它们偶尔会工作 为什么它只能在本地主机上失败 客户端来源 #include <unistd.h> #i
echo“show version”| nc-q1 127.0.0.1 5000
给出:
Command received: show version
Beta
我有一个客户端,它的行为应该与命令行测试完全相同,但是它挂起在第二个read()
调用上,除非我在不同的服务器上运行它。我对unix域套接字也有同样的问题,只是它们偶尔会工作
为什么它只能在本地主机上失败
客户端来源
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#define ERR_FAIL_CONNECT -1
#define ERR_SOCK_SELECT -2
#define ERR_SOCK_READ -3
#define ERR_SOCK_WRITE -3
#define ERR_SOCK_REMOTE_CLOSED -4
int tcpConnect (char *ipAddr, int port);
int sendCommand (char *buf, int bufSize);
int readWithTimeout (int sock, char *buf, int bufSize, struct timeval *timeout);
int main() {
char buf[64];
int nBytes;
strcpy(buf, "show version");
nBytes = sendCommand(buf, sizeof(buf));
printf("Response: %s\n", buf);
return 0;
}
int sendCommand (char *buf, int bufSize) {
int apiSock;
int nBytes = ERR_SOCK_SELECT;
int len;
struct timeval timeout;
apiSock = tcpConnect("127.0.0.1", 5000);
if (!apiSock) return ERR_FAIL_CONNECT;
len = strlen(buf);
nBytes = write(apiSock, buf, len);
if (nBytes < 0) {
perror("ERROR writing to socket");
nBytes = ERR_SOCK_WRITE;
}
else if (nBytes < len) {
fprintf(stderr, "Command truncated at %d/%d\n", nBytes, len);
nBytes = ERR_SOCK_WRITE;
}
else {
timeout.tv_sec = 3;
timeout.tv_usec = 0;
nBytes = readWithTimeout(apiSock, buf, bufSize, &timeout);
if (nBytes > 0) {
timeout.tv_sec = 20;
timeout.tv_usec = 0;
nBytes = readWithTimeout(apiSock, buf, bufSize, &timeout);
}
}
close(apiSock);
return nBytes;
}
int tcpConnect (char *ipAddr, int port) {
struct sockaddr_in addr;
int sock;
sock = socket(AF_INET, SOCK_STREAM, 0);
if (sock == -1) {
perror("ERROR: Could not create TCP socket");
return 0;
}
addr.sin_addr.s_addr = inet_addr(ipAddr);
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
if (connect(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
perror("ERROR: Could not connect");
return 0;
}
return sock;
}
int readWithTimeout (int sock, char *buf, int bufSize, struct timeval *timeout) {
int res;
int nBytes = ERR_SOCK_SELECT;
fd_set set;
fprintf(stderr, "readWithTimeout(sock=%d, buf='%s', bufSize=%d, timeout{tv_sec=%d, tv_usec=%d})\n",
sock, buf, bufSize, timeout->tv_sec, timeout->tv_usec);
FD_ZERO(&set);
FD_SET(sock, &set);
res = select(sock+1, &set, NULL, NULL, timeout);
if (res < 0) perror("ERROR waiting for data");
else if (res == 0) fprintf(stderr, "Timed out waiting for data\n");
else {
nBytes = read(sock, buf, bufSize);
if (nBytes < 0) {
perror("ERROR reading from socket");
nBytes = ERR_SOCK_READ;
}
else if (nBytes == 0) {
fprintf(stderr, "Remote end closed socket\n");
shutdown(sock, 2);
close(sock);
nBytes = ERR_SOCK_REMOTE_CLOSED;
}
}
return nBytes;
}
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#define TCP_PORT 5000
#define BUF_SIZE 512
int readCommand(int clientSockFd);
void myWrite (int fileDescriptor, const void *buf, size_t nbytes);
int main (void) {
socklen_t client_len;
int optval;
int flags;
struct sockaddr_in serv_addr, client_addr;
int serverSockFd;
int clientSockFd;
fd_set set;
struct timeval timeout;
int rv;
serverSockFd = socket(AF_INET, SOCK_STREAM, 0);
if(serverSockFd < 0) perror("ERROR opening socket");
bzero((char *) &serv_addr, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = INADDR_ANY;
serv_addr.sin_port = htons(TCP_PORT);
if(bind(serverSockFd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) {
perror("Unable to bind TCP socket");
}
listen(serverSockFd, 5);
client_len = sizeof(client_addr);
flags = fcntl(serverSockFd, F_GETFL, 0);
if (flags < 0) perror("Unable to read TCP socket flags");
flags = flags|O_NONBLOCK;
fcntl(serverSockFd, F_SETFL, flags);
// Wait for client connections
while(1) {
clientSockFd = accept(serverSockFd, (struct sockaddr *) &client_addr, &client_len);
if(clientSockFd < 0) {
usleep(50000);
continue;
}
//After connected, inner loop to read and write multiple packages
while(1) {
FD_ZERO(&set);
FD_SET(clientSockFd, &set);
timeout.tv_sec = 15;
timeout.tv_usec = 0;
rv = select(clientSockFd+1, &set, NULL, NULL, &timeout);
if(rv == -1) {
perror("select");
continue;
}
else if(rv == 0) {
printf("TCP timeout, closing client connection.\n");
shutdown(clientSockFd, 2);
break;
}
if (!readCommand(clientSockFd)) break;
}
close(clientSockFd);
}
close(serverSockFd);
return 0;
}
int readCommand(int sock) {
int nBytes;
int len;
char inBuf[BUF_SIZE];
char outBuf[BUF_SIZE];
nBytes = read(sock, inBuf, BUF_SIZE);
if(nBytes < 0) perror("ERROR reading from TCP socket");
else if(nBytes == 0) {
printf("Client closed TCP socket\n");
shutdown(sock, 2);
return nBytes;
}
else {
// Acknowledge command
len = sprintf(outBuf, "Command received: %s", inBuf);
if (write(sock, outBuf, len+1) < 0) {
perror("ERROR writing to TCP socket");
}
// Send response data
if (!strncmp("show version", inBuf, 12)) strcpy(outBuf, "Beta");
else strcpy(outBuf, "Invalid command");
if (write(sock, outBuf, strnlen(outBuf, BUF_SIZE-1)+1) < 0) {
perror("ERROR writing to TCP socket");
}
}
return nBytes;
}
#包括
#包括
#包括
#包括
#包括
#包括
#定义ERR\u FAIL\u CONNECT-1
#定义ERR_SOCK_SELECT-2
#定义ERR_SOCK_READ-3
#定义ERR_SOCK_WRITE-3
#定义ERR\u SOCK\u REMOTE\u CLOSED-4
int TCP连接(字符*ipAddr,int端口);
int sendCommand(字符*buf,int bufSize);
int readWithTimeout(int sock,char*buf,int bufSize,struct timeval*timeout);
int main(){
char-buf[64];
整数字节;
strcpy(buf,“显示版本”);
nBytes=sendCommand(buf,sizeof(buf));
printf(“响应:%s\n”,buf);
返回0;
}
int sendCommand(字符*buf,int bufSize){
int apiSock;
int nBytes=错误存储选择;
内伦;
结构timeval超时;
apiSock=TCP连接(“127.0.0.1”,5000);
如果(!apiSock)返回ERR\u FAIL\u CONNECT;
len=strlen(buf);
nBytes=写入(apiSock、buf、len);
如果(n字节<0){
perror(“写入套接字时出错”);
n字节=错误写入;
}
else if(n字节0){
timeout.tv_sec=20;
timeout.tv_usec=0;
nBytes=readWithTimeout(apiSock、buf、bufSize和timeout);
}
}
关闭(apiSock);
返回n字节;
}
int TCP连接(字符*ipAddr,int端口){
地址中的结构sockaddr\u;
int袜子;
sock=socket(AF\u INET,sock\u STREAM,0);
如果(sock==-1){
perror(“错误:无法创建TCP套接字”);
返回0;
}
addr.sin\u addr.s\u addr=inet\u addr(ipAddr);
addr.sin_family=AF_INET;
地址SINU port=htons(端口);
if(connect(sock,(struct sockaddr*)&addr,sizeof(addr))<0){
perror(“错误:无法连接”);
返回0;
}
返回袜子;
}
int readWithTimeout(int sock、char*buf、int bufSize、struct timeval*timeout){
国际关系;
int nBytes=错误存储选择;
fd_集;
fprintf(stderr,“readWithTimeout(sock=%d,buf='%s',bufSize=%d,timeout{tv\u sec=%d,tv\u usec=%d})\n”,
sock,buf,bufSize,超时->电视秒,超时->电视秒;
FD_零位(&set);
FD_套装(袜子和套装);
res=select(sock+1,&set,NULL,NULL,timeout);
if(res<0)perror(“等待数据的错误”);
如果(res==0)fprintf(stderr,“等待数据超时”\n);
否则{
nBytes=读取(sock、buf、bufSize);
如果(n字节<0){
perror(“从套接字读取错误”);
n字节=错误存储读取;
}
else if(n字节==0){
fprintf(stderr,“远程端闭合套接字”\n);
停机(sock,2);
关闭(袜子);
n字节=错误\u套接字\u远程\u关闭;
}
}
返回n字节;
}
服务器源
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#define ERR_FAIL_CONNECT -1
#define ERR_SOCK_SELECT -2
#define ERR_SOCK_READ -3
#define ERR_SOCK_WRITE -3
#define ERR_SOCK_REMOTE_CLOSED -4
int tcpConnect (char *ipAddr, int port);
int sendCommand (char *buf, int bufSize);
int readWithTimeout (int sock, char *buf, int bufSize, struct timeval *timeout);
int main() {
char buf[64];
int nBytes;
strcpy(buf, "show version");
nBytes = sendCommand(buf, sizeof(buf));
printf("Response: %s\n", buf);
return 0;
}
int sendCommand (char *buf, int bufSize) {
int apiSock;
int nBytes = ERR_SOCK_SELECT;
int len;
struct timeval timeout;
apiSock = tcpConnect("127.0.0.1", 5000);
if (!apiSock) return ERR_FAIL_CONNECT;
len = strlen(buf);
nBytes = write(apiSock, buf, len);
if (nBytes < 0) {
perror("ERROR writing to socket");
nBytes = ERR_SOCK_WRITE;
}
else if (nBytes < len) {
fprintf(stderr, "Command truncated at %d/%d\n", nBytes, len);
nBytes = ERR_SOCK_WRITE;
}
else {
timeout.tv_sec = 3;
timeout.tv_usec = 0;
nBytes = readWithTimeout(apiSock, buf, bufSize, &timeout);
if (nBytes > 0) {
timeout.tv_sec = 20;
timeout.tv_usec = 0;
nBytes = readWithTimeout(apiSock, buf, bufSize, &timeout);
}
}
close(apiSock);
return nBytes;
}
int tcpConnect (char *ipAddr, int port) {
struct sockaddr_in addr;
int sock;
sock = socket(AF_INET, SOCK_STREAM, 0);
if (sock == -1) {
perror("ERROR: Could not create TCP socket");
return 0;
}
addr.sin_addr.s_addr = inet_addr(ipAddr);
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
if (connect(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
perror("ERROR: Could not connect");
return 0;
}
return sock;
}
int readWithTimeout (int sock, char *buf, int bufSize, struct timeval *timeout) {
int res;
int nBytes = ERR_SOCK_SELECT;
fd_set set;
fprintf(stderr, "readWithTimeout(sock=%d, buf='%s', bufSize=%d, timeout{tv_sec=%d, tv_usec=%d})\n",
sock, buf, bufSize, timeout->tv_sec, timeout->tv_usec);
FD_ZERO(&set);
FD_SET(sock, &set);
res = select(sock+1, &set, NULL, NULL, timeout);
if (res < 0) perror("ERROR waiting for data");
else if (res == 0) fprintf(stderr, "Timed out waiting for data\n");
else {
nBytes = read(sock, buf, bufSize);
if (nBytes < 0) {
perror("ERROR reading from socket");
nBytes = ERR_SOCK_READ;
}
else if (nBytes == 0) {
fprintf(stderr, "Remote end closed socket\n");
shutdown(sock, 2);
close(sock);
nBytes = ERR_SOCK_REMOTE_CLOSED;
}
}
return nBytes;
}
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#define TCP_PORT 5000
#define BUF_SIZE 512
int readCommand(int clientSockFd);
void myWrite (int fileDescriptor, const void *buf, size_t nbytes);
int main (void) {
socklen_t client_len;
int optval;
int flags;
struct sockaddr_in serv_addr, client_addr;
int serverSockFd;
int clientSockFd;
fd_set set;
struct timeval timeout;
int rv;
serverSockFd = socket(AF_INET, SOCK_STREAM, 0);
if(serverSockFd < 0) perror("ERROR opening socket");
bzero((char *) &serv_addr, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = INADDR_ANY;
serv_addr.sin_port = htons(TCP_PORT);
if(bind(serverSockFd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) {
perror("Unable to bind TCP socket");
}
listen(serverSockFd, 5);
client_len = sizeof(client_addr);
flags = fcntl(serverSockFd, F_GETFL, 0);
if (flags < 0) perror("Unable to read TCP socket flags");
flags = flags|O_NONBLOCK;
fcntl(serverSockFd, F_SETFL, flags);
// Wait for client connections
while(1) {
clientSockFd = accept(serverSockFd, (struct sockaddr *) &client_addr, &client_len);
if(clientSockFd < 0) {
usleep(50000);
continue;
}
//After connected, inner loop to read and write multiple packages
while(1) {
FD_ZERO(&set);
FD_SET(clientSockFd, &set);
timeout.tv_sec = 15;
timeout.tv_usec = 0;
rv = select(clientSockFd+1, &set, NULL, NULL, &timeout);
if(rv == -1) {
perror("select");
continue;
}
else if(rv == 0) {
printf("TCP timeout, closing client connection.\n");
shutdown(clientSockFd, 2);
break;
}
if (!readCommand(clientSockFd)) break;
}
close(clientSockFd);
}
close(serverSockFd);
return 0;
}
int readCommand(int sock) {
int nBytes;
int len;
char inBuf[BUF_SIZE];
char outBuf[BUF_SIZE];
nBytes = read(sock, inBuf, BUF_SIZE);
if(nBytes < 0) perror("ERROR reading from TCP socket");
else if(nBytes == 0) {
printf("Client closed TCP socket\n");
shutdown(sock, 2);
return nBytes;
}
else {
// Acknowledge command
len = sprintf(outBuf, "Command received: %s", inBuf);
if (write(sock, outBuf, len+1) < 0) {
perror("ERROR writing to TCP socket");
}
// Send response data
if (!strncmp("show version", inBuf, 12)) strcpy(outBuf, "Beta");
else strcpy(outBuf, "Invalid command");
if (write(sock, outBuf, strnlen(outBuf, BUF_SIZE-1)+1) < 0) {
perror("ERROR writing to TCP socket");
}
}
return nBytes;
}
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#定义TCP_端口5000
#定义BUF_大小512
int readCommand(int clientSockFd);
void myWrite(int fileDescriptor,const void*buf,size\u t nbytes);
内部主(空){
socklen_u t client_len;
int optval;
国际旗帜;
服务地址、客户端地址中的结构sockaddr\u;
int-serverSockFd;
int clientSockFd;
fd_集;
结构timeval超时;
int-rv;
serverSockFd=socket(AF\u INET,SOCK\u STREAM,0);
if(serverSockFd<0)perror(“错误打开套接字”);
bzero((char*)&serv_addr,sizeof(serv_addr));
serv_addr.sin_family=AF_INET;
serv_addr.sin_addr.s_addr=INADDR_ANY;
serv_addr.sin_port=htons(TCP_端口);
if(bind(serverSockFd,(struct sockaddr*)&serv_addr,sizeof(serv_addr))<0{
perror(“无法绑定TCP套接字”);
}
听(5);
客户地址=sizeof(客户地址);
flags=fcntl(serverSockFd,F_GETFL,0);
如果(标志<0)或(“无法读取TCP套接字标志”);
标志=标志| O|非块;
fcntl(服务器sockfd、F_SETFL、标志);
//等待客户端连接
而(1){
clientSockFd=accept(serverSockFd,(struct sockaddr*)&client\u addr,&client\u len);
if(clientSockFd<0){
美国LEEP(50000);
持续
}
//连接后,内部循环读取和写入多个包
而(1){
FD_零位(&set);
FD_集(clientSockFd,&SET);
timeout.tv_sec=15;
timeout.tv_usec=0;
rv=select(clientSockFd+1,&set,NULL,NULL,&timeout);
如果(rv==-1){
佩罗(“选择”);
持续
}
否则如果(rv==0){
printf(“TCP超时,关闭客户端连接。\n”);
关闭(clientSockFd,2);
打破
}
如果(!readCommand(clientSockFd))中断;
}
关闭(clientSockFd);
}
关闭(serverSockFd);
返回0;
}
int readCommand(int sock){
整数字节;
内伦;
字符inBuf[BUF_大小];
字符大小[BUF_SIZE];
n字节=读取(sock、inBuf、BUF_大小);
如果(n字节<0)perror(“从TCP套接字读取错误”);
else if(n字节==0){
printf(“客户端关闭的TCP套接字”);
停机(sock,2);
返回n字节;
}
否则{
//确认命令
len=sprintf(exputf,“收到的命令:%s”,i