Title:
[purpose]
Understand and be familiar with socket based communication in Linux environment. The local interprocess communication mode is limited to a single computer. The socket based communication mode can not only realize the interprocess communication in a single computer, but also realize the communication between different computer processes. File operation is one of the most common operations in Linux system. Be familiar with the file system of Linux and the related system calls of its operation, and understand and master the file I/O operation mode based on file descriptor and data flow.
[experimental preparation content]
(1) Read the references of relevant chapters such as network programming and file I/O operation under Linux.
(2) Focus on network programming mode and file I/O operation based on data flow
[experiment content]
Read resources, analyze the sample program code, and program in C language to achieve the following requirements.
- The socket communication mechanism is used to send and receive information between the client process and the server process;
- And use file I/O operation to read and save the transmission and reception of information.
Student No.: 021900208 Name: Gao Xu major: Computer Science and technology class: 02
1, Experimental environment:
Oracle VM VirtualBox,Ubuntu(64-bit)
2, Experiment content:
Code part
ex3.h// ex3.h #include <stdio.h> #include <stdlib.h> #include <string.h> #include <errno.h> #include <fcntl.h> #include <sys/types.h> #include <netinet/in.h> #include <arpa/inet.h> #include <unistd.h> #include <sys/socket.h> #include <signal.h> #include <netdb.h> #define ARFILE "./usr.ar" / / specify the path name of the archive file struct arstruct // Employee data structure { char name[10]; int age; char tele[21]; }; // Delete employee function int removeuser(char *name) { struct arstruct ar; FILE *fp; FILE *fpn; if((fpn = fopen("./tmpfile","w")) == NULL) { return 0; } if((fp = fopen(ARFILE,"r")) == NULL) { return 0; } while(fread(&ar,sizeof(ar),1,fp) == 1) // Copy circularly. Those matching the input name will not be copied { if(strcmp(name,ar.name) != 0) { fwrite(&ar,sizeof(ar),1,fpn); // If not, copy } memset(&ar,0x00,sizeof(ar)); } fclose(fp); fclose(fpn); remove(ARFILE); // Delete original file rename("./tmpfile",ARFILE); // The copied new file is renamed as an archive file return 1; } // Query employee function int queryuser(char *name) { int found = 0; struct arstruct ar; FILE *fp; if((fp = fopen(ARFILE,"r")) == NULL) { return 0; } while(fread(&ar,sizeof(ar),1,fp) == 1) { if(strcmp(name,ar.name) == 0) { found = 1; break; } memset(&ar,0x00,sizeof(ar)); } fclose(fp); return found; } // Add employee function int insertuser(struct arstruct tmpar) { struct arstruct ar; FILE *fp; if((fp = fopen(ARFILE,"a")) == NULL) { return 0; } memset(&ar,0x00,sizeof(ar)); strcpy(ar.name,tmpar.name); strcpy(ar.tele,tmpar.tele); ar.age=tmpar.age; if(fwrite(&ar,sizeof(ar),1,fp) < 0) { perror("fwrite"); fclose(fp); return 0; } fclose(fp); return 1; } // Modify employee function int updateuser(struct arstruct new_ar) { struct arstruct old_ar; FILE *fp; fpos_t pos; int found=0; int cnt=0; if((fp = fopen(ARFILE,"r+")) == NULL) { return 0; } while(fread(&old_ar, sizeof(old_ar), 1, fp) == 1) // Copy circularly. Those matching the input name will not be copied { if(strcmp(old_ar.name,new_ar.name) != 0) { cnt++; } else if(strcmp(old_ar.name, new_ar.name) == 0) { found = 1; pos.__pos = (long)(cnt * sizeof(struct arstruct)); // Set the amount of movement to one structure fsetpos(fp, &pos); // Another method of moving file pointer position fwrite(&new_ar, sizeof(new_ar), 1, fp); } memset(&old_ar,0x00,sizeof(old_ar)); } if(found) { return 1; } else { return -1; } }Server code: new1.c
// new1.c #include "ex3.h" #define MAXSIZE 1024 / / buffer size int main(int argc, char *argv[]) { int sockfd,new_fd; // Defines the variable that holds the socket descriptor struct sockaddr_in server_addr; // Define the server-side socket data structure_ addr struct sockaddr_in client_addr; // Define the client socket data structure client_addr struct arstruct ar; int server_len, client_len; // Server and client message length int nbytes,portnumber; int age; char name[10]; char buf[MAXSIZE]; char rebuf[MAXSIZE]; if(argc!=2) { fprintf(stderr,"Usage:%s portnumber\a\n",argv[0]); exit(1); } if((portnumber=atoi(argv[1]))<0) // Get the second parameter on the command line -- port number. atoi() converts the string to an integer { fprintf(stderr,"Usage:%s portnumber\a\n",argv[0]); exit(1); } if((sockfd=socket(AF_INET,SOCK_STREAM,0))==-1) // The server starts to create the socket descriptor { fprintf(stderr,"Socket error:%s\n\a",strerror(errno)); exit(1); } bzero(&server_addr,sizeof(struct sockaddr_in)); // First clear the socket address data structure server_addr.sin_family=AF_INET; // Set as TCP/IP address family server_addr.sin_addr.s_addr=htonl(INADDR_ANY); // Set the local address and convert from host byte order to network byte order*/ server_addr.sin_port=htons(portnumber); // Set the port number and convert from host byte order to network byte order*/ if(bind(sockfd,(struct sockaddr *)(&server_addr),sizeof(struct sockaddr))==-1) // Call the bind function to bind the specified port number and ip address to the socket created by the server { fprintf(stderr,"Bind error:%s\n\a",strerror(errno)); exit(1); } if(listen(sockfd,5)==-1) // The port binding is successful. Listen to the sockfd descriptor and set the maximum number of connection requests processed at the same time to 5*/ { fprintf(stderr,"Listen error:%s\n\a",strerror(errno)); exit(1); } client_len = sizeof(client_addr); // Receive client connection request new_fd = accept(sockfd,(struct sockaddr *) &client_addr,(socklen_t *__restrict) &client_len); while(1) { memset(rebuf,0x00,sizeof(rebuf)); read(new_fd,rebuf,sizeof(rebuf)); printf("Client message received: %s\n",rebuf); // Output to terminal if(rebuf[0] == '1') { write(new_fd,"Please enter your name",MAXSIZE); // Reply message read(new_fd,rebuf,sizeof(rebuf)); strcpy(ar.name,rebuf); printf("Client name message received: %s\n",ar.name); // Output to terminal write(new_fd,"Please enter age",MAXSIZE); // Reply message read(new_fd,rebuf,sizeof(rebuf)); age=atoi(rebuf); ar.age=age; printf("Client age message received: %d\n",age); // Output to terminal write(new_fd,"Please enter the employee's mobile phone number",MAXSIZE); // Reply message read(new_fd,rebuf,sizeof(rebuf)); strcpy(ar.tele,rebuf); printf("Received client mobile number message: %s\n",ar.tele); // Output to terminal if(insertuser(ar)) { write(new_fd,"Success in adding new employees...\n",MAXSIZE); } else { write(new_fd,"An error occurred while adding members...\n",MAXSIZE); } } else if(rebuf[0] == '2') { write(new_fd,"Please enter your name",MAXSIZE); // Reply message read(new_fd,rebuf,sizeof(rebuf)); printf("Receive the message of querying employee name from the client: %s\n",rebuf); // Output to terminal if(queryuser(rebuf)) { write(new_fd,"Query the employee data\n",MAXSIZE); } else { write(new_fd,"No data found for this employee...\n",MAXSIZE); } } else if(rebuf[0]== '3') { write(new_fd,"Please enter employee name:",MAXSIZE); // Reply message read(new_fd,rebuf,10); strcpy(name,rebuf); printf("Received client delete employee name message: %s\n",name); // Output to terminal if(removeuser(name)) { write(new_fd,"Employee data deleted successfully...\n",MAXSIZE); } else { write(new_fd,"An error occurred while deleting employee data...\n",MAXSIZE); } } else if(rebuf[0] == '4') { write(new_fd,"Please enter your name",MAXSIZE); // Reply message read(new_fd,rebuf,sizeof(rebuf)); strcpy(ar.name,rebuf); printf("Received a message from the client to modify the employee name: %s\n",rebuf); // Output to terminal write(new_fd,"Please enter age",MAXSIZE); // Reply message read(new_fd,rebuf,sizeof(rebuf)); age=atoi(rebuf); ar.age=age; printf("Received the message of modifying employee age from the client: %d\n",age); // Output to terminal write(new_fd,"Please enter the employee's mobile phone number",MAXSIZE); // Reply message read(new_fd,rebuf,sizeof(rebuf)); strcpy(ar.tele,rebuf); printf("Received the message that the client modifies the employee's mobile phone number: %s\n",rebuf); // Output to terminal int ret = updateuser(ar); if(ret == 1) { write(new_fd,"Employee data modified successfully...\n",MAXSIZE); } else if(ret == -1) { write(new_fd,"There is no data for this employee...\n",MAXSIZE); } else { write(new_fd,"An error occurred while modifying employee data...\n",MAXSIZE); } } else if(rebuf[0] == '0') { break; } } return 0; }Client code: new2.c
// new2.c #include "ex3.h" #define MAXSIZE 1024 / / buffer size int main(int argc, char *argv[]) { int new_fd; char buf[MAXSIZE]; char rebuf[MAXSIZE]; char c; struct sockaddr_in server_addr; // Define the server-side socket data structure_ addr struct hostent *host; // Defines a pointer to the host structure struct arstruct ar; int portnumber,nbytes; if(argc!=3) { fprintf(stderr,"Usage:%s hostname portnumber\a\n",argv[0]); exit(1); } if((host=gethostbyname(argv[1]))==NULL) // Get the hostent pointer containing the address through the domain name or hostname { fprintf(stderr,"Gethostname error\n"); exit(1); } if((portnumber=atoi(argv[2]))<0) { fprintf(stderr,"Usage:%s hostname portnumber\a\n",argv[0]); exit(1); } if((new_fd = socket(AF_INET,SOCK_STREAM,0))==-1) { fprintf(stderr,"Socket Error:%s\a\n",strerror(errno)); exit(1); } bzero(&server_addr,sizeof(server_addr)); server_addr.sin_family=AF_INET; server_addr.sin_port=htons(portnumber); server_addr.sin_addr=*((struct in_addr *)host->h_addr); if(connect(new_fd,(struct sockaddr *)(&server_addr),sizeof(struct sockaddr))==-1) { fprintf(stderr,"Connect Error:%s\a\n",strerror(errno)); exit(1); } else { fprintf(stdout,"Connection succeeded\n"); } printf(" *Employee file management system*\n"); printf("---------------------------\n"); printf(" 1.Enter new employee file \n"); printf(" 2.View employee profile \n"); printf(" 3.Delete employee file \n"); printf(" 4.Modify employee file \n"); printf(" 0.Exit the system \n"); printf("---------------------------\n"); while(1) { printf("Please enter:"); scanf("%s",buf); write(new_fd,buf,sizeof(buf)); // send message if(buf[0] == '0') { break; } read(new_fd,rebuf,sizeof(rebuf)); // Receive new messages printf("Server message received:%s\n",rebuf); // Output to terminal } printf("End communication\n"); close(new_fd); return 0; }
Screenshot of experimental results:
3, Experiment summary:
1. The idea of the program:
- Rewrite the code 3-6 of the example to ex3.h, so that the server program can call the function to maintain the employee system
- In the employee system, the function of using flow location to modify the employee system is added
- The running process is: the client accesses the server program, and the server receives the client request to query, insert, delete and modify the employee system
2. What knowledge did you learn by yourself in this experiment
① File descriptor
② Open / close and read / write of stream
③ Flow location
④ Network programming principle
⑤ Socket descriptor
⑥ Socket read / write
⑦ TCP socket communication flow
3. Difficulties and solutions in this experiment:
① The parameters of read/write function and recv/send function
② Call socket descriptor as parameter
③ Buffer send
④ There is a problem deleting the employee function (unresolved)