Socket programming: recv/read issue
编辑:下面的代码已修复,可以正确接收和发送,并且考虑到已发送和接收到的消息的实际字节数(这要归功于EJP)
我正在Unix中使用C编程。
我有应该交换消息的服务器和客户端。虽然客户端似乎可以很好地发送消息,但是服务器没有收到客户端正在发送的消息。我试过使用
每次发送消息后,我都会在客户端代码中放入
这是客户端代码:
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); |
您正在
接收器侧:
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 |
您应该从
尝试在
该实现是基于流还是数据报?
您的操作流程存在一些问题。服务器可能在客户端发送任何内容之前开始读取。
由于客户端和服务器是分开的,因此可以想象它们同时运行。
在您的服务器端"接受"连接请求之后,可能会发生一些握手开销,或者网络延迟导致服务器应用程序提前执行,尝试提取数据但遇到错误(尚未接收到数据)。
您可以通过在接受连接后在服务器代码中添加睡眠来进行尝试,其中客户端应该有足够的时间来发送数据。
另一个更好的解决方案是使数据检索处理空缓冲区或异步读取。