クライアントが接続してコマンドを待機できるサーバーTCPソケットをプログラムする方法を学んでいます...
fd = open("/tmp/myFIFO", O_RDWR);
if(fd<0){
perror("open() error");
exit(1);
}
do {
while ((nbytes = read(fd, buffer, sizeof(buffer)-1)) > 0) {
buffer[nbytes] = '\0';
printf("%s\n", buffer);
}
err = recv(cFD, strbuf, sizeof(strbuf), 0);
if (err < 0) {
if (errno != EWOULDBLOCK) {
perror(" recv() failed");
state = TRUE;
}
break;
}
if (err == 0) {
printf(" Connection closed\n");
state = TRUE;
break;
}
dSize = err;
printf(" %d bytes received\n", dSize);
err = send(cFD, buffer, strlen(buffer), 0);
if (err < 0) {
perror(" send() failed");
state = TRUE;
break;
}
} while (TRUE);
問題が発生しているコードの一部を取得するだけです。私はパイプから読んでいます。私はそれを使用してクライアントにメッセージを送信しています..しかし、私の問題はrecvにあります。パイプから読み取ったデータをクライアントに送信する前に、クライアントから送信されたデータを待ちます。私がやりたいことは、データをパイプに送信するたびに、recv を待たずにクライアントに直接送信されることです。これはどのように行うことができますか?
完全なコードは次のとおりです。
#include <stdio.h>
#include <stdlib.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <netinet/in.h>
#include <errno.h>
#include <string.h>
#include <sys/select.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <pthread.h>
#define TRUE 1
#define FALSE 0
typedef struct SERVER_FD{
int sPort;
int serverFD;
int smaxFD;
int newFD;
}sSD;
int cFD,
dSize,
err,
start = 1,
state,
DescRead,
DCSERVER = FALSE;
struct sockaddr_in addr, cli_addr;
unsigned long ip;
char strbuf[256];
socklen_t clilen;
fd_set fdin, fduse;
pid_t pid, sid;
int fd=-1;
int nbytes;
char buffer[256];
void process(int ServerFD, int Port, int sMax, int NewSFD);
void cleanUP(int i, int max);
void dlogs(unsigned long ip);
void daemonize();
main (int argc, char *argv[])
{
sSD link;
sSD *sCon;
sCon = &link;
sCon->sPort = 53234;
fd = open("/tmp/myFIFO", O_RDWR);
if(fd<0){
perror("open() error");
exit(1);
}
printf("Starting Server-G\n");
fcntl(fd, F_SETFL,
fcntl(fd, F_GETFL) | O_NONBLOCK);
sCon->serverFD = socket(AF_INET, SOCK_STREAM, 0);
if (sCon->serverFD != -1) {
err = setsockopt(sCon->serverFD, SOL_SOCKET, SO_REUSEADDR,(char *)&start, sizeof(start));
if (err != -1) {
err = ioctl(sCon->serverFD, FIONBIO, (char *)&start);
if (err != -1){
process(sCon->serverFD,sCon->sPort,sCon->smaxFD,sCon->newFD);
}
else{
perror("ioctl() failed");
close(sCon->serverFD);
exit(EXIT_FAILURE);
}
}
else{
perror("setsockopt() failed");
close(sCon->serverFD);
exit(EXIT_FAILURE);
}
}
else{
perror("FAILED CONNECTING TO SOCKET");
exit(EXIT_FAILURE);
}
}
void process(int ServerFD, int Port, int sMax, int NewSFD){
bzero((char *) &addr, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = 0;
addr.sin_port = htons(Port);
err = bind(ServerFD,(struct sockaddr *)&addr, sizeof(addr));
if (err < 0) {
perror("bind() failed");
close(ServerFD);
exit(EXIT_FAILURE);
}
daemonize();
err = listen(ServerFD, 32);
if (err < 0) {
perror("listen() failed");
close(ServerFD);
exit(EXIT_FAILURE);
}
clilen = sizeof(cli_addr);
FD_ZERO(&fdin);
sMax = ServerFD;
FD_SET(ServerFD, &fdin);
do {
fduse = fdin;
err = select(sMax + 1, &fduse, NULL, NULL, NULL);
if (err < 0) {
perror(" select() failed");
break;
}
DescRead = err;
for (cFD=0; cFD <= sMax && DescRead > 0; ++cFD) {
if (FD_ISSET(cFD, &fduse)) {
DescRead -= 1;
if (cFD == ServerFD) {
do {
NewSFD = accept(ServerFD,(struct sockaddr *) &cli_addr, &clilen);
if (NewSFD < 0) {
if (errno != EWOULDBLOCK) {
perror(" accept() failed");
DCSERVER = TRUE;
}
break;
}
ip = ntohl(cli_addr.sin_addr.s_addr);
printf(" Connection from %d.%d.%d.%d\n",
(int)(ip>>24)&0xff,
(int)(ip>>16)&0xff,
(int)(ip>>8)&0xff,
(int)(ip>>0)&0xff);
dlogs(ip);
FD_SET(NewSFD, &fdin);
if (NewSFD > sMax)
sMax = NewSFD;
} while (NewSFD != -1);
}
else {
state = FALSE;
do {
//PART WHERE I'm Having problems.
err = recv(cFD, strbuf, sizeof(strbuf), 0);
if (err < 0) {
if (errno != EWOULDBLOCK) {
perror(" recv() failed");
state = TRUE;
}
break;
}
if (err == 0) {
printf(" Connection closed\n");
state = TRUE;
break;
}
dSize = err;
printf(" %d bytes received\n", dSize);
while ((nbytes = read(fd, buffer, sizeof(buffer)-1)) > 0) {
buffer[nbytes] = '\0';
printf("%s\n", buffer);
}
err = send(cFD, buffer, strlen(buffer), 0);
if (err < 0) {
perror(" send() failed");
state = TRUE;
break;
}
} while (TRUE);
if (state) {
close(fd);
close(cFD);
FD_CLR(cFD, &fdin);
if (cFD == sMax) {
while (FD_ISSET(sMax, &fdin) == FALSE)
sMax -= 1;
}
}
}
}
}
} while (DCSERVER == FALSE);
cleanUP(cFD, sMax);
}
void cleanUP(int i, int max){
for (i=0; i <= max; ++i) {
if (FD_ISSET(i, &fdin))
close(i);
}
}
void dlogs(unsigned long ip){
FILE* pFile = fopen("/sockF.txt", "a+");
fprintf(pFile,"Connection from: %d.%d.%d.%d",
(int)(ip>>24)&0xff,
(int)(ip>>16)&0xff,
(int)(ip>>8)&0xff,
(int)(ip>>0)&0xff);
fclose(pFile);
}
void daemonize(){
pid = fork();
if(pid<0){
perror("fork() failed");
exit(EXIT_FAILURE);
}
if(pid>0){
exit(EXIT_SUCCESS);
}
umask(0);
sid = setsid();
if(sid<0){
perror("setsid() failed");
exit(EXIT_FAILURE);
}
if((chdir("/")) < 0){
perror("failed changing directory");
exit(EXIT_FAILURE);
}
}
サンプル出力: サーバーのテストに telnet と putty を使用しています
From Telnet: IP: 192.168.5.53
Telnet 192.168.5.55 53234
./socks
Starting Server-G
Connection from: 192.168.5.53
telnetが接続されたら、パテを使用してパイプにデータを送信し、サーバーがデータを読み取るようにします。
From Putty:
echo "TEST" > /tmp/myFIFO
ここでの問題は、パテ書き込みからパイプにデータを送信するたびに、サーバーが出力してパイプに書き込んだデータを送信する前に、telnet がデータを送信するのを待機することです。recv と read の両方を同じ tym で動作させるにはどうすればよいですか?
ありがとう
編集:パイプを読み取るためにスレッドも使用しましたが、パイプに読み取られたものをサーバーが出力する前に recv() を待機します。