我正在编程服务器/客户端程序,这里有一个奇怪的问题.... 服务器绑定套接字并侦听套接字。但它仍然坚持接受客户。它是银行计划的模拟。服务器存储一个帐户的余额并执行客户想要的操作。奇怪的情况是我接受时没有错误消息,服务器在控制台“已接受”上打印我的消息,但它没有执行下一条打印消息。但是将余额写入客户端的确很好,因为客户端获得了正确的价值.....服务器也忽略了下一条打印消息.....这里有什么不对吗?该程序还没有准备好,我只是在这里测试一些功能。
#include <stdio.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <netdb.h>
#include <arpa/inet.h>
#define MAX 20
int main(int argc, char **argv){
int sockfd,csocket;
struct sockaddr_in addr,client_addr;
socklen_t clilen;
clilen = sizeof(client_addr);
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0) {
fprintf(stderr, "Error in opening socket - %s\n", strerror(errno));
return EXIT_FAILURE;
}
addr.sin_family = AF_INET;
addr.sin_port = htons(atoi(argv[1]));
addr.sin_addr.s_addr = htonl(INADDR_ANY);
if (bind(sockfd, (struct sockaddr *) &addr, sizeof(struct sockaddr_in)) < 0){
fprintf(stderr, "Error in binding - %s\n", strerror(errno));
return EXIT_FAILURE;
}
printf("Bind\n");
int list = listen(sockfd, SOMAXCONN);
if (list < 0) {
fprintf(stderr, "Error in listening - %s\n", strerror(errno));
return EXIT_FAILURE;
}
printf("Listening\n");
char sel;
int tmp,bal=666;
while(1) {
//newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen);
csocket = accept(sockfd,(struct sockaddr *) &client_addr,&clilen);
if (csocket < 0) {
fprintf(stderr, "Error in accepting - %s\n", strerror(errno));
return EXIT_FAILURE;
}
printf("Accepted\n");
printf("Writing balance");
if (write(csocket,&bal,sizeof(int))<0){
fprintf(stderr, "Error in Writing - %s", strerror(errno));
return EXIT_FAILURE;
}
printf("Writing balance");
if(read(csocket, &sel, sizeof(char))<0){
fprintf(stderr, "Error in reading - %s\n", strerror(errno));
return EXIT_FAILURE;
}
printf("User wählt:%c\n",sel);
/********Einzahlen**********/
if (sel=='e'){
printf("Neuer Kontostand: %d", bal);
if(read(csocket, &tmp, sizeof(int))<0){
fprintf(stderr, "Error in accepting - %s\n", strerror(errno));
return EXIT_FAILURE;
}
bal+=tmp;
printf("Neuer Kontostand: %d", bal);
}
if(sel=='q'){
close(csocket);
printf("User beendet\n");
}
}
}
客户
{add include part here}
int main(){
int sockfd;
socklen_t addrlen;
addrlen = sizeof(struct sockaddr_in);
struct sockaddr_in addr;
sockfd = socket(AF_INET, SOCK_STREAM, 0);
char ip[16];
printf("IP (Press 0 for 127.0.0.1):");
scanf("%15s", ip);
//printf("\n");
if (ip[0]=='0'){
strcpy(ip,DEFAULT_IP);
printf("Setting IP to 127.0.0.1\n");
}
printf("%s",ip);
int port;
printf("Port:");
scanf("%d",&port);
printf("\n");
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
addr.sin_addr.s_addr=inet_addr(ip);
int tmp;
if (connect(sockfd, (struct sockaddr *) &addr, sizeof(struct sockaddr_in))<0){
fprintf(stderr, "Error in connecting - %s\n", strerror(errno));
}
printf("Connected\n");
int bal,w;
if(read(sockfd, &bal, sizeof(int))<0){
fprintf(stderr, "Error in accepting - %s\n", strerror(errno));
return EXIT_FAILURE;
}
printf("Balance:%d\n",bal);
printf("Geld [e]inzahlen\n"); //add money to account
printf("Geld [a]uszahlen\n"); //Getting money from account
char msg[MAX];
printf("Enter your choce:\n");
scanf("%s",msg);
if (msg[0]=='e'){
printf("How much?:\n");
scanf("%i",&w);
if (write(sockfd,&w,sizeof(int))<0 ){
fprintf(stderr, "Error in Writing - %s", strerror(errno));
return EXIT_FAILURE;
}
bal+=w;
}
printf("sended");
if (close(sockfd) < 0) {
fprintf(stderr, "Error in closing socket - %s\n", strerror(errno));
}
}
答案 0 :(得分:1)
当前的问题是两件事的结合。
首先,在没有换行的情况下打印“已接受”。标准输出是行缓冲的,因此在打印换行符(或从stdin
读取输入或显式fflush(stdout);
)之前不会打印。
其次,然后输入read
,显然永远不会返回。从理论上讲,write
也可以阻止,但是你说客户端会收到写入,因此服务器必须停留在read
。
最终结果,您的服务器程序无限期地停留在读取状态。您认为打印的输出卡在stdout
缓冲区,等待刷新。
原因很简单:您的客户端只写4个字节,但您的服务器尝试读取4 + 1个字节。实际上它是服务器上的第二个read
,它无限期地阻塞。
一些一般提示:
scanf
函数的返回值,如果您正在从键盘读取用户输入,请加倍。即使它只是实验性代码,您也不希望浪费时间来解决不是错误的错误,而是scanf
的正常行为。答案 1 :(得分:0)
您需要调用select()函数来测试文件描述符是否在accept()之前就绪。还要查找fd_set和相关的FD_ZERO,FD_SET和FD_ISSET宏。需要它们来监视套接字是否已准备好接受传入连接。对于套接字编程来说,这是一个很棒的resource。