关于C#:Socket编程:接收/读取问题

Socket programming: recv/read issue

编辑:下面的代码已修复,可以正确接收和发送,并且考虑到已发送和接收到的消息的实际字节数(这要归功于EJP)

我正在Unix中使用C编程。

我有应该交换消息的服务器和客户端。虽然客户端似乎可以很好地发送消息,但是服务器没有收到客户端正在发送的消息。我试过使用recv()read()(我知道它们实际上是同一件事,但是在recv()上带有额外的标志),但是我没有运气,而且我不确定问题的根源。

每次发送消息后,我都会在客户端代码中放入sleep(3),但是我看到,一旦客户端和服务器连接,服务器将立即关闭,而无需等待传入的消息。我在做什么错?

这是客户端代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
#define SERVER_TCP_PORT 11112
#define MAX_DATA_SIZE   500

int main(int argc, char * argv[])
{
    int sockfd;
    char * host;
    char msg[MAX_DATA_SIZE];/* ="get my msg!\
";*/

    int msg_len;

    struct hostent * hp;
    struct sockaddr_in client_address, server_address;


    printf("y halo thar\
"
);


    // looking up from the host database
    if (argc == 2)
        host = argv[1];
    else
        exit(1);
    printf("sdf\
"
);


    hp = gethostbyname(host);
    if (!hp)
        exit(1);
    printf("host found\
"
);


    // setting up address and port structure information
    bzero((char * ) &server_address, sizeof(server_address)); // copy zeroes into string
    server_address.sin_family = AF_INET;
    bcopy(hp->h_addr, (char *) &server_address.sin_addr, hp->h_length);
    server_address.sin_port = htons(SERVER_TCP_PORT);
    printf("set\
"
);


    // opening up socket
    if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0 )
        exit(1);
    printf("opened\
"
);


    // connecting
    if (connect(sockfd, (struct sockaddr *) &server_address, sizeof(server_address)) < 0)
        exit(1);
    printf("connected\
"
);


    int i;

    for (i = 0; i < MAX_DATA_SIZE; ++i)
    {
        msg[i] = '.';
    }

    msg[MAX_DATA_SIZE-1] = '\\0';

    for(i = 0; i < 11; i++)
    {
        // send message to connected socket
        msg_len = write(sockfd, msg, MAX_DATA_SIZE);
        if(msg_len < 1)
            printf("notsent\
"
);
        else
            printf("%i  bytes sent\
"
, msg_len);

        // recieve messages from connected socket
        msg_len = read(sockfd, msg, MAX_DATA_SIZE);
        if (msg_len < 1)
            printf("not recieved\
"
);
        else
        {
            printf("%i bytes received\
"
, msg_len);
            printf(msg);
            printf("\
"
);

        }
    }


    // close connection
    close(sockfd);
    printf("closed\
"
);

}

这是服务器端

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
#define SERVER_TCP_PORT 11112
#define MAX_DATA_SIZE   500


int main()
{

    printf("o halo thar\
"
);

    int sockfd, new_sockfd;
    int client_addr_len;
    char msg [MAX_DATA_SIZE];
    int msg_len;
    char got_msg [11] ="got ur msg\\0";
    struct sockaddr_in server_address, client_address;


    // setting up address and port structure information
    bzero((char * ) &server_address, sizeof(server_address)); // copy zeroes into string
    server_address.sin_family = AF_INET;
    server_address.sin_addr.s_addr = htonl(INADDR_ANY);
    server_address.sin_port = htons(SERVER_TCP_PORT);


    // opening up socket
    if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0 )
        exit(1);
    printf("socket is opened\
"
);


    // binding
    if (bind(sockfd, (struct sockaddr *) &server_address, sizeof(server_address)) < 0)
        exit(1);
    printf("socket is bound\
"
);


    // listening
    listen(sockfd,5);
    printf("listening\
"
);

    // block and wait for an incoming connection

    client_addr_len = sizeof(client_address);
    new_sockfd = accept(sockfd, (struct sockaddr *) &client_address, &client_addr_len);
    if (new_sockfd < 0)
        exit(1);

    printf("accepted\
"
);


    int i;

    for( i = 0; i < 11; i++)
    {
        // recieve messages from connected socket
        printf("waiting\
"
);
        msg_len = read(new_sockfd, msg, MAX_DATA_SIZE);
        if (msg_len < 1)
        {
            printf("no msg recieved\
"
);    
        }
        else
        {
            printf("bytes recieved: %i\
"
, msg_len);
        }


        // send message to connected socket
        msg_len = write(new_sockfd, got_msg, sizeof(got_msg));
        if (msg_len < 1)
            printf("not sent\
"
);
        else
            printf("%i bytes sent\
"
, msg_len);
    }


    // close connection
    close(sockfd);
    printf("socket closed. BYE! \
"
);


}

在服务器代码中,问题出在以下一行:

1
msg_len = read(sockfd, msg, MAX_DATA_SIZE);

您正在sockfd上调用read,但是您需要在new_sockfd(accept()返回的套接字)上调用readrecvnew_sockfd是连接到客户端的一个(sockfd用于接受其他连接-例如,如果另一个客户端连接)。


接收器侧:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
   while(1)
    {      
        len=read(sd,buff,sizeof(buff));

        if(len==0)
        {
            //End of File receving.            

            break;
        }
        else    
        {  
            st=fwrite(buff,sizeof(char),len,fp);

        }
    }

发送侧:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
while(!feof(fp))
{
    len=fread(buff,sizeof(char),MW,fp);
    if(len==0)
    {
      //EOF
      st=write(cd,&d,sizeof(int));      
      break;
    }
    else
    {
        st=write(cd,buff,len);
    }
}

您应该从accept返回的套接字中读取。

尝试在accept返回的socket上调用read


该实现是基于流还是数据报?

您的操作流程存在一些问题。服务器可能在客户端发送任何内容之前开始读取。

由于客户端和服务器是分开的,因此可以想象它们同时运行。
在您的服务器端"接受"连接请求之后,可能会发生一些握手开销,或者网络延迟导致服务器应用程序提前执行,尝试提取数据但遇到错误(尚未接收到数据)。
您可以通过在接受连接后在服务器代码中添加睡眠来进行尝试,其中客户端应该有足够的时间来发送数据。

另一个更好的解决方案是使数据检索处理空缓冲区或异步读取。