Я сделал tcp сервер и клиент. Он работает нормально, моя единственная проблема в том, что я хочу, чтобы клиент продолжал спрашивать меня о вводе, я попытался поместить его в цикл, но он работает только для одной итерации, а затем останавливается.
Server.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h> // struct sockaddr_in
// FIX HERE
// Let's limit our message length to a single byte.
// This makes sending the "length" marker easier
// without worrying about byte-ordering (endianness).
#define MAX_LEN 255
int main(int argc, char **argv)
{
int sock, newsock;
struct sockaddr_in server_addr;
struct sockaddr_in client_addr;
socklen_t client_addrlen; // client address length (in and out)
int err_code;
int num_bytes;
char buf[MAX_LEN];
char t[12]={0x0};
float total=0;
float temp=0;
if (argc < 2) {
fprintf(stderr, "Error, no port provided.\n");
exit(0);
}
// create socket
sock = socket(AF_INET, SOCK_STREAM, 0);
if (sock < 0) {
perror("socket");
exit(1);
}
// build local internet addr/port
memset(&server_addr, 0, sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = INADDR_ANY;
server_addr.sin_port = htons(atoi(argv[1]));
// bind the socket to local internet addr/port
err_code = bind(sock, (struct sockaddr *)&server_addr, sizeof(server_addr));
if (err_code < 0) {
perror("bind");
exit(2);
}
// put server socket in listening state
err_code = listen(sock, 5);
if (err_code < 0) {
perror("listen");
exit(3);
}
while (1) {
// accept new connection (returns new socket)
client_addrlen = sizeof(client_addr); // must set (used as input)
newsock = accept(sock, (struct sockaddr *)&client_addr, &client_addrlen);
// above call also sets the client_addr and client_addrlen
// so that we know which client is connected to the server
if (newsock < 0) {
perror("accept");
exit(4);
}
//
// receive data from new socket (FIX HERE)
//
// Check how client sends the message with a marker.
// You got to receive the message according to how
// the client sends it.
//
unsigned char msglen;
recv(newsock, &msglen, 1, 0); // receive the length marker
unsigned total_bytes_received = 0;
while (total_bytes_received < msglen) {
num_bytes = recv(newsock, buf+total_bytes_received,
msglen-total_bytes_received, 0);
if (num_bytes < 0) {
perror("recv");
exit(5);
}
total_bytes_received += num_bytes;
}
temp=atof(buf);
total+=temp;
sprintf(t, "%f",total);
// display the received message
printf("Received a datagram (%i): ", msglen); fflush(stdout);
//write(1, "Received a datagram: ", 21);
write(1,&t, sizeof(t)); // FIX HERE(total_bytes_received)
printf("\n");
//
// acknowledge the receipt of the message from client (FIX HERE)
//
// DO THE SAME AS HOW CLIENT SENDS A MESSAGE WITH A LENGTH MARKER!
//
char *ack_msg = "Got your message\n";
msglen = strlen(ack_msg);
send(newsock, &msglen, 1, 0); // Send marker
num_bytes = send(newsock, ack_msg, msglen, 0); // send ack message
if (num_bytes < 0) {
perror("sendto");
exit(6);
}
// close new socket
//close(newsock);
}
// close passive socket
//close(sock);
return 0;
}
Client.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
// FIX HERE
// Let's limit our message length to a single byte.
// This makes sending the "length" marker easier
// without worrying about byte-ordering (endianness).
#define MAX_LEN 255
int main(int argc, char **argv)
{
int sock;
struct sockaddr_in server_addr;
struct hostent *hp;
char buf[MAX_LEN];
int num_bytes;
int err_code;
if (argc != 3) {
fprintf(stderr, "Usage: %s server port\n", argv[0]);
exit(0);
}
// create socket
sock = socket(AF_INET, SOCK_STREAM, 0);
if (sock < 0) {
perror("socket");
exit(1);
}
// resolve server name for its IP address, etc.
hp = gethostbyname(argv[1]);
if (NULL == hp) {
perror("gethostbyname");
exit(2);
}
// build remote server addr/port
memset(&server_addr, 0, sizeof(server_addr));
server_addr.sin_family = AF_INET;
memcpy(&server_addr.sin_addr, hp->h_addr, hp->h_length);
server_addr.sin_port = htons(atoi(argv[2]));
// connect to server
err_code = connect(sock, (struct sockaddr *)&server_addr, sizeof(server_addr));
if (err_code < 0) {
perror("connect");
exit(3);
}
//while loop start
while(1){
// ask user for a message to be sent
printf("Please enter a message: ");
memset(buf , 0, MAX_LEN);
fgets(buf, MAX_LEN, stdin);
//
// send message (FIX HERE)
//
// With stream paradigm, you CANNOT just send your
// message without proper marker. Otherwise, you
// will not be able to know how much data to expect
// to receive on the receiving side.
//
// For this simple example, we will send a one-byte
// length before each message to be sent.
//
unsigned char msglen = strlen(buf);
send(sock, &msglen, 1, 0);
num_bytes = send(sock, buf, strlen(buf), 0);
if (num_bytes < 0) {
perror("send");
exit(4);
}
//
// receive message (FIX HERE)
//
// This got to be symmetrical. Before receiving
// the message, we expect to receive a one-byte
// length field that tells us how long the message
// to receive is.
//
// We will receive the message in a loop as it is
// not guaranteed we will receive the entire message
// in one shot. The length field we receive allows
// us to determine when to terminate the loop.
//
recv(sock, &msglen, 1, 0);
unsigned total_bytes_received = 0;
while (total_bytes_received < msglen) {
num_bytes = recv(sock, buf+total_bytes_received,
msglen-total_bytes_received, 0);
// NOTE: the parameters passed to the above recv call!!!
if (num_bytes < 0) {
perror("recv");
exit(5);
}
total_bytes_received += num_bytes;
}
// display received ack message
printf("Got an ack (%d): ", msglen); fflush(stdout);
//write(1, "Got an ack: ", 12);
write(1, buf, total_bytes_received); // FIX HERE
printf("\n");
}//end while loop
// close sock to release resource
close(sock);
return 0;
}
Как вы можете видеть, попытался поместить цикл while, где пользователю предлагается отправить сообщениесервер, сервер предназначен для ответа клиенту о том, что сообщение принято, и распечатывает сообщение на стороне сервера. Это все работает только один раз, после чего клиент завершает работу. Я хочу сделать так, чтобы он мог зацикливаться и спрашивать бесконечное количество раз, пока я не уйду.