2014-08-29 30 views
0

我正尝试使用Linux中的C网络编程读取和写入套接字。我分别在客户端和服务器程序中成功调用“写入”和“读取”。使用读取和写入功能的C中的套接字错误

我很难理解的部分是,在我的客户端程序中,我在服务器上循环并调用write 5次不同的时间,我循环并调用read 5次不同的次数。

这是预期的输出:

MSG: I got your message MSG: I got your message MSG: I got your message MSG: I got your message MSG: I got your message 

这是实际的输出:

MSG: I got your messageI got your messageMSG: I got your messageI got your messageMSG: I got your messageMSG: MSG: 

正如你所看到的预期输出和实际输出是不同的。看起来客户端能够在实际发送之前调用“写入”两次。

这是我的客户端代码

for(int i=0;i<5;i++) 
{ 
    int n = write(ssocket.socketFileDescriptor,"I got your message",18); 
    cout<<n<<" number of bytes written."<<endl; 
    if (n < 0) socketError("ERROR writing to socket"); 
} 

这是服务器代码:

void* run(void* arg) 
{ 
    ServerSocket* ss = (ServerSocket*)arg; 
    //while(true) 
    for(int i=0;i<5;i++) 
    { 
     char buffer[256]; 
     bzero(buffer,256); 
     int n = read(ss->newsockfd,buffer,256); 
     printf("MSG: %s",buffer); 
    } 
    close(ss->newsockfd); 
} 

这是除了问题,下面这是过时的,在这一点上。

我缺少一个调用刷新或什么的?

Simulate Java's Thread class in C++

+1

您假定TCP可以传输大于一个字节的消息。它不能 - 它是一个字节/八位字节的STREAMING协议,并且不知道一个字节之上的消息边界。如果您想传输更大,更复杂的消息,则需要TCP上的协议。这个问题有无数次 - 这么多,我不能看着:) – 2014-08-29 21:08:54

+0

如果你使用的TCP套接字,然后发送的所有内容连接成一个流,当它被读取时,你会得到什么是可用的直到缓冲区大小)。您需要插入自己的消息边界并在接收器中解析流。 – molbdnilo 2014-08-29 21:12:04

+0

所以我打开wireshark并确认每个'写'调用实际上创建了它自己的数据包。 所以这意味着阅读是双倍的。这是我看到'读',我说在我的代码中读取256个字节。 – Matthew 2014-08-30 19:56:18

回答

2

你的客户端和服务器只是没有协调。客户端尽可能快地将消息写入5次,并且服务器尽可能快地读取5次。在您的示例输出中,显然在第一次拨打read()时,客户端发送了两次消息,在第二次拨打read()时,又发送了两次。你最多可以有256个字符,每次你调用它时,它只会尝试读取当前在缓冲区中的任何内容。如果客户在那个时候发送了多封邮件,read()只会抓住一切。

您通常需要某种类型的同步,例如,发送一条消息后,客户端会在发送第二条消息之前等待服务器发送"OK"或类似内容。除此之外,如果您的通信格式非常简单,则可以使用某种类型的消息结束标记(例如换行符),以便服务器区分它们。

+0

或者只是在两边添加缓冲(服务器和客户端)。 – 2014-08-29 21:12:12

+0

是的!我想添加缓冲,但我不完全知道如何做到这一点。我正在尝试创建一个类似于Java的系统,以及所有使用BufferedFileReader构建的系统或其他... 你如何做缓冲?另外,说我想发送更多的256个字符没有响应?我怎么做?我假设这个套接字使用TCP,所以我不应该承认无论如何,虽然正确? – Matthew 2014-08-29 21:25:40

+0

@Matthew:你最好的选择是使用许多第三方网络库之一。实现缓冲并不是那么困难,但也并非完全微不足道。你可以通过每次read()一个字符来实现一个穷人的版本,直到你碰到行尾字符,接收未知长度的行。使用单字符的系统调用效率相对较低,但除非您正在编写大容量服务器,否则网络可能会成为瓶颈。 – 2014-08-29 21:29:47