- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在学习如何编写服务器 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。它会等待客户端发送的数据,然后将从我的管道读取的数据发送到客户端。我想要发生的是,每次我向管道发送数据时,它都会直接发送到客户端,而无需等待接收。如何做到这一点?
完整代码如下:
#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 连接时,我使用 putty 将数据发送到管道,以便服务器读取它。
From Putty:
echo "TEST" > /tmp/myFIFO
这里的问题是,每当我将 putty 中的数据发送到管道时,服务器都会等待 telnet 发送数据,然后再输出并将我写入的数据发送到管道。我怎样才能使recv和read同时工作,这样当我写入管道时,它就会输出而无需等待recv?
谢谢
编辑:我还使用线程来读取管道,但在服务器输出已读取到管道的内容之前它仍然等待recv()。
最佳答案
使用select
或poll
等待两个文件句柄上的事件,例如。 (使用民意调查
)
#include <poll.h>
//...
struct pollfd pfds[2];
int rc;
/* Wait for input on either one of the fds */
pfds[0].fd = fd;
pfds[0].events = POLLIN;
pfds[1].fd = cFD;
pfds[1].events = POLLIN;
do {
/* Wait forever for something to happen */
rc = poll(&pfds, 2, -1);
/* Error handling elided */
if (pfds[0].revents & POLLIN)
{
/* Read from fd, change pfds[1].events to (POLLIN | POLLOUT) so you know when you
can write without blocking. also clear pfds[0].events so we don't read until we
write */
pfds[0].events = 0;
pfds[1].events = POLLIN | POLLOUT;
}
if (pfds[1].revents & POLLIN)
{
/* Read from socket */
}
if (pfds[1].revents & POLLOUT)
{
/* write to socket, reset events flags */
pfds[0].events = POLLIN;
pfds[1].events = POLLIN;
}
} while (1)
关于c - receive() read() 和 send() 无需等待,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13008514/
我很难理解为什么这段代码无法编译: use std::cell::{Ref, RefCell}; struct St { data: RefCell } impl St { pub f
我从Richard Blum的一本书《 C#网络编程》中读到有关套接字的信息。以下摘录指出,不保证Send()方法可以发送所有传递给它的数据。 byte[] data = new byte[1024]
我有以下程序,它必须一次读取 1MB 的文件,将其发送到服务器(每次总是 1MB)并返回哈希码: #include #include #include #include #include #
代码在底部。 第 207 行的 send() 命令本身可以正常工作。但是,当我在第 218 行添加 send() 命令时,第一个命令失败 - 给出错误“地址错误”。我已经确认第二个 send() 命令
标记包含 !Send 的类型背后的原因是什么?字段(如 Rc 或 NonNull )与 Send特征?例如,标准库的 LinkedList 以这种方式工作:它包含 Option>字段并实现 Send特
我是新手,我正在尝试学习 goroutines 中信号函数的一些基本用法。我在 go 中有一个无限循环。通过这个 for 循环,我通过 channel 将值传递给 goroutine。 我也有一个阈值
如果数据是从另一台计算机(首先)“发送”的,我如何设置我的套接字例程以“发送”(首先)或(切换)“接收”? 谢谢 通用代码: -(void) TcpClient{ char buffer[12
这个问题已经有答案了: Java multiple file transfer over socket (3 个回答) 已关闭 4 年前。 我正在使用 Java Socket 将文件发送到服务器,然后
根据以下示例中的类型,Go编译器似乎将执行两个完全不同的语义操作: chanA <-chanB 如果chanA是类型(chan chan <-字符串),则此操作会将本身类型chanB的类型(chan
我正在尝试在 VBA 中使用 WinSock2 从本地主机 TCP 流发送(以及稍后接收)数据。 目前,我主要尝试从此处复制客户端示例,https://msdn.microsoft.com/en-us
我在我的 Mac OS X Yosemite 控制台中看到了这个: AppleEvents: Send port for process has no send right, port=( port:
我知道Clojure的“代理”是ref,带有“操作”的添加工作队列。 Action 是使用ref的值在第一个位置调用的函数,可以将其传递给其他参数。操作将返回ref的新值。因此,“代理”是一种计算re
我无法将任何对象或数组传递给 IPCRenderer。 通过 ipcs 传递对象或数组时出现错误,我什至尝试通过使用 JSON.stringify 转换为字符串来发送,但它会将其转换为空对象字符串。
我正在使用unix scoket进行数据传输(SOCK_STREAM模式) 我需要发送超过100k个字符的字符串。首先,我发送一个字符串的长度-它是sizeof(int)个字节。 length = s
Clojure API 将这两个函数描述为: (send a f & args) - Dispatch an action to an agent. Returns the agent immedia
def send_Button(): try: myMsg = "ME: " + text.get() msg = text.get() con
Ruby 对象都有一个“发送”方法,但是,我正在尝试使用一个 Java 库 ( netty-tools ),它的一个接口(interface)上有一个“发送”方法。 用法应该是 java_obj.se
Feb 8, 2011 11:56:49 AM com.sun.xml.internal.messaging.saaj.client.p2p.HttpSOAPC onnection post SEVE
来自 man 2 send: MSG_MORE (since Linux 2.4.4) (…) Since Linux 2.6, this flag is also supported for UDP
我的网页中可以有一个按钮,用于将预填充的消息发送到特定号码吗? 我正在尝试 intent://send/+391234567890#Intent;scheme=smsto;package=com.wh
我是一名优秀的程序员,十分优秀!