【发布时间】:2016-08-05 07:55:11
【问题描述】:
我已经为一个简单的客户端/服务器编写了代码。代码在运行时执行以下操作。
首先,服务器等待来自客户端的消息,然后要求用户输入要发送给客户端的消息。当客户端第一次开始运行时,它会要求用户输入要发送到服务器的消息,然后等待服务器的回复。
当我将第一条消息从客户端发送到服务器时,程序运行良好,它出现了,然后服务器要求我写一条消息发送给客户端,问题开始了:
我键入消息并按 Enter 消息被发送到客户端,然后服务器收到相同的先前消息并提示我为客户端输入消息。从服务器或客户端发送的消息不会立即被读取和打印,除非我在服务器中键入另一条消息,然后它会显示从客户端发送的上一条消息。
服务器代码:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <netdb.h>
static void bail( const char* on_what ){
fputs(strerror(errno),stderr);
fputs(": ",stderr);
fputs(on_what,stderr);
fputc('\n',stderr);
exit(1);
}
int main(int argc, char** argv) {
int sockfd, bindfd, listenfd, acceptfd, writefd, readfd, len_inet;
struct sockaddr_in address_server, address_client;
char *server_address = "192.168.1.10";
char *server_portno = "9100";
char readBuffer[256], writeBuffer[256];
memset(&address_server, 0, sizeof address_server);
address_server.sin_family = AF_INET;
address_server.sin_port = htons(atoi(server_portno));
address_server.sin_addr.s_addr = inet_addr(server_address);
if(address_server.sin_addr.s_addr == INADDR_NONE)
bail("bad address");
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if( sockfd == -1 )
bail("socket()");
printf("socket created\n");
bindfd = bind(sockfd, (struct sockaddr *)&address_server, sizeof address_server);
if( bindfd == -1 )
bail("bind()");
printf("bind done\n");
listenfd = listen(sockfd, 10);
if( listenfd == -1 )
bail("listen()");
printf("Listening to Client\n");
len_inet = sizeof address_client;
acceptfd = accept(sockfd, (struct sockaddr *)&address_client, &len_inet);
if( acceptfd == -1 )
bail("accept()");
printf("Connection accepted\n");
while(1){
printf("Reading from Client...\n");
readfd = read(acceptfd, &readBuffer, sizeof readBuffer-1);
if( readfd == -1 )
bail("read()");
printf("Message from Client: %s\n", readBuffer);
printf("Enter a message to send to Client:\n");
fgets(writeBuffer, 255, stdin);
writefd = write(acceptfd, writeBuffer, sizeof writeBuffer);
if( writefd == -1 )
bail("write()");
}
close(acceptfd);
printf("Closing Connection\n");
return (EXIT_SUCCESS);
}
客户代码:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <netinet/in.h>
void static bail( const char* on_what ){
fputs(strerror(errno),stderr);
fputs(": ",stderr);
fputs(on_what,stderr);
fputc('\n',stderr);
exit(1);
}
int main(int argc, char** argv){
int sockfd, connectfd, readfd, writefd, len_inet;
struct sockaddr_in address_server;
char *server_address = "192.168.1.240";
char *server_portno = "9100";
char readBuffer[256], writeBuffer[256];
memset(&address_server, 0, sizeof address_server);
address_server.sin_family = AF_INET;
address_server.sin_port = htons(atoi(server_portno));
address_server.sin_addr.s_addr = inet_addr(server_address);
if( address_server.sin_addr.s_addr == INADDR_NONE)
bail("bad address");
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if( sockfd == -1 )
bail("socket()");
printf("socket created\n");
len_inet = sizeof address_server;
connectfd = connect(sockfd, (struct sockaddr *)&address_server, len_inet);
if( connectfd == -1 )
bail("connect()");
printf("Connected\n");
while(1){
printf("Please enter a message to send to the Server: \n");
fgets(writeBuffer, 255, stdin);
writefd = write(sockfd, writeBuffer, sizeof writeBuffer);
if( writefd == -1 )
bail("write(2)");
printf("Waiting for a message from the server\n");
readfd = read(sockfd, &readBuffer, sizeof readBuffer-1);
if( readfd == -1 )
bail("read(2)");
readBuffer[readfd] = 0;
printf("Message from the server: %s\n", readBuffer);
}
close(sockfd);
printf("Connection Closed\n");
return 0;
}
【问题讨论】:
-
为了便于我们人类理解和阅读:1) 一致地缩进。在每个左大括号 '{' 后缩进。在每个右大括号 '}' 之前取消缩进。
-
在“if()”语句之后缩进多个语句不会使多个语句成为“if”代码块的一部分。仅将语句包装在大括号中即可。
-
编译时始终启用所有警告,然后修复这些警告。 (对于
gcc,至少使用:-Wall -Wextra -pedantic我也使用:-Wconversion -std=gnu99)发布的代码导致编译器引发大量警告消息。所有这些警告都需要纠正。 -
在现代 C 语言中,修饰符
static位于函数的返回类型之前。 -
为了便于理解,便于文档,便于调试;遵循公理:每行只有一个语句,并且(最多)每个语句一个变量声明。
标签: c sockets tcp server client