TCP経由で通信するC言語の単純なクライアントおよびサーバープログラムがあります。クライアントはメッセージをサーバーに送信し、サーバーはそれをファイルに書き込みます。
クライアントがEOF文字を読み取るまで無期限にループし、サーバーがリクエストを処理し続ける必要があります。ただし、現時点では、ループに問題があります。ループなしで正常に動作しますが、クライアントに while(1) を配置すると、サーバーは最初の要求を正常に処理しますが、2 番目の要求は何もせず、3 番目の要求はパイプの破損エラーを引き起こします。これは、サーバーがソケットを閉じるのが早すぎるためだと思いますが、修正方法に行き詰まっています。
これが私のクライアントプログラムです:
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <ctype.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#define BUFFERLENGTH 256
/* displays error messages from system calls */
void error(char *msg)
{
perror(msg);
exit(0);
}
int main(int argc, char *argv[])
{
int sockfd, portno, n;
struct sockaddr_in serv_addr;
struct hostent *server;
char buffer[BUFFERLENGTH];
if (argc < 3) {
fprintf (stderr, "usage %s hostname port\n", argv[0]);
exit(1);
}
/* create socket */
portno = atoi (argv[2]);
sockfd = socket (AF_INET, SOCK_STREAM, 0);
if (sockfd < 0)
error ("ERROR opening socket");
/* enter connection data */
server = gethostbyname (argv[1]);
if (server == NULL) {
fprintf (stderr, "ERROR, no such host\n"); // error message for when the provided hostname doesn't exist.
exit (1);
}
bzero ((char *) &serv_addr, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
bcopy ((char *)server->h_addr,
(char *)&serv_addr.sin_addr.s_addr,
server->h_length);
serv_addr.sin_port = htons (portno);
/* connect to the server */
if (connect (sockfd, (struct sockaddr *) &serv_addr, sizeof (serv_addr)) < 0)
error ("ERROR connecting");
while(1){
/* prepare message */
printf ("Please enter the message: ");
bzero (buffer, BUFFERLENGTH);
fgets (buffer, BUFFERLENGTH, stdin);
/* send message */
n = write (sockfd, buffer, strlen(buffer));
if (n < 0)
error ("ERROR writing to socket");
bzero (buffer, BUFFERLENGTH);
/* wait for reply */
n = read (sockfd, buffer, BUFFERLENGTH -1);
if (n < 0)
error ("ERROR reading from socket");
printf ("%s\n",buffer);
}
return 0;
}
そしてサーバーコード:
/* A threaded server which uses TCP to communicate with clients.
Passes the port number and a file name in as arguments.
Receives log entries from the clients and writes them to the file. */
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <ctype.h>
#include <stdlib.h>
#include <strings.h>
#include <string.h>
#include <unistd.h>
#include <pthread.h>
#define BUFFERLENGTH 256
/* displays error messages from system calls */
void error(char *msg)
{
perror(msg);
exit(1);
}
FILE *file;
int returnValue;
pthread_mutex_t mut; /* the lock */
/* the procedure called for each request */
void *processRequest (void *args) {
int *newsockfd = (int *) args;
char buffer[BUFFERLENGTH];
int n, formed = 0;
n = read (*newsockfd, buffer, BUFFERLENGTH -1);
if (n < 0)
error ("ERROR reading from socket");
printf ("Here is the message: %s\n",buffer);
pthread_mutex_lock (&mut); /* lock exclusive access to variable isExecuted */
//const char* string = "hello world";
char buffer2[256];
char* walker;
int colon = 0;
strcpy(buffer2,buffer);
walker=buffer2;
while(colon == 0){
if(*walker == ':'){ // if it encounters a colon will successfully exit the loop.
colon = 1;
}
if(*walker == '\0'){ // if it encounters the end of the string, will break the loop.
break;
}
if(isalnum(*walker)){ // if it's not an alphanumeric character then it will break the loop, otherwise it will continue.
walker++;
} else {
break;}
}
if(colon == 1){ // if the loop found a colon, then it will continue to search the rest of the string.
while(*walker >= 32 && *walker<= 126){
++walker;
if(*walker == '\n'){
printf("Entry well formed.\n");
fprintf(file,"%s",buffer); /*writes*/
fclose(file); /*done!*/
formed = 1;
}
}
} else{
perror("Entry not well formed.\n");
}
pthread_mutex_unlock (&mut); /* release the lock */
if(formed==1){
n = sprintf (buffer, "Message received and written to file.\n");
}else{
n = sprintf (buffer, "Message received but was not well formed and was not written to file.\n");
}
/* send the reply back */
n = write (*newsockfd, buffer, BUFFERLENGTH);
if (n < 0)
error ("ERROR writing to socket");
close (*newsockfd); /* important to avoid memory leak */
free (newsockfd);
returnValue = 0; /* cannot guarantee that it stays constant */
pthread_exit (&returnValue);
}
int main(int argc, char *argv[])
{
socklen_t clilen;
int sockfd, portno;
char buffer[BUFFERLENGTH];
struct sockaddr_in serv_addr, cli_addr;
pthread_t *server_thread;
int result;
if (argc < 3) {
fprintf (stderr,"ERROR, arguments: port filename.\n"); /* Error message for if there isn't enough arguments. */
exit(1);
}
/* create socket */
sockfd = socket (AF_INET, SOCK_STREAM, 0);
if (sockfd < 0)
error("ERROR opening socket");
bzero ((char *) &serv_addr, sizeof(serv_addr));
portno = atoi(argv[1]);
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = INADDR_ANY;
serv_addr.sin_port = htons (portno);
/* bind it */
if (bind(sockfd, (struct sockaddr *) &serv_addr,
sizeof(serv_addr)) < 0)
error("ERROR on binding");
/* ready to accept connections */
listen (sockfd,5);
clilen = sizeof (cli_addr);
/* now wait in an endless loop for connections and process them */
while (1) {
file = fopen(argv[2], "a");
if (file == NULL) {
printf("I couldn't open results.txt for writing.\n");
exit(0);
}
int *newsockfd; /* allocate memory for each instance to avoid race condition */
pthread_attr_t pthread_attr; /* attributes for newly created thread */
newsockfd = malloc (sizeof (int));
if (!newsockfd) {
fprintf (stderr, "Memory allocation failed!\n");
exit (1);
}
/* waiting for connections */
*newsockfd = accept(sockfd,
(struct sockaddr *) &cli_addr,
&clilen);
if (*newsockfd < 0)
error ("ERROR on accept");
bzero (buffer, BUFFERLENGTH);
/* create separate thread for processing */
server_thread = malloc (sizeof (pthread_t));
if (!server_thread) {
fprintf (stderr, "Couldn't allocate memory for thread!\n");
exit (1);
}
if (pthread_attr_init (&pthread_attr)) {
fprintf (stderr, "Creating initial thread attributes failed!\n");
exit (1);
}
if (pthread_attr_setdetachstate (&pthread_attr, !PTHREAD_CREATE_DETACHED)) {
fprintf (stderr, "setting thread attributes failed!\n");
exit (1);
}
result = pthread_create (server_thread, &pthread_attr, processRequest, (void *) newsockfd);
if (result != 0) {
fprintf (stderr, "Thread creation failed!\n");
exit (1);
}
}
return 0;
}