一、客户机程序代码
1、程序:client.c
2、目的:创建一个套接字,通过网络连接一个服务器,并打印来自服务器的信息
#include<stdlib.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <netdb.h> #include <stdio.h> #include <string.h> #define PROTOPORT 5188 extern int errno; char localhost[] = "localhost"; main(int argc, char *argv[]){ struct hostent *ptrh; struct sockaddr_in servaddr; int sockfd; int port; char* host; int n; char buf[1000]; memset((char*)& servaddr, 0, sizeof(servaddr)); servaddr.sin_family = AF_INET; if(argc > 2){ port = atoi(argv[2]); }else{ port = PROTOPORT; } if(port > 0){ servaddr.sin_port = htons((u_short)port); }else{ fprintf(stderr,"bad port number %s\n",argv[2]); } if(argc > 1){ host = argv[1]; }else{ host = localhost; } ptrh = gethostbyname(host); if((char*)ptrh == NULL){ fprintf(stderr,"invalid host:%s\n",host); exit(1); } memcpy(&servaddr.sin_addr,ptrh->h_addr,ptrh->h_length); sockfd = socket(AF_INET,SOCK_STREAM,0); if(sockfd < 0){ fprintf(stderr,"socket creation failed\n"); exit(1); } if(connect(sockfd,(struct sockaddr*)&servaddr,sizeof(servaddr)) < 0){ fprintf(stderr,"connect failed\n"); exit(1); } n = recv(sockfd, buf, sizeof(buf), 0); while(n > 0){ write(1,buf,n); n = recv(sockfd, buf, sizeof(buf), 0); } close(sockfd); exit(0); }
二、服务器实例代码
1、程序:server.c
2、目的:分配一个套接字,然后反复执行如下几步:
1)等待客户的下一个连接
2)发送一个短消息给客户
3)关闭与客户的连接
4)转向第1步
#include<stdlib.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <stdio.h> #include <string.h> #define PROTOPORT 5188 #define QLEN 6 int visits = 0; main(int argc, char* argv[]) { struct hostent* ptrh; struct sockaddr_in servaddr; struct sockaddr_in clientaddr; int listenfd; int clientfd; int port; int alen; char buf[1000]; memset( (char*)& servaddr, 0, sizeof(servaddr) ); servaddr.sin_family = AF_INET; servaddr.sin_addr.s_addr = INADDR_ANY; if(argc > 1){ port = atoi(argv[1]); }else{ port = PROTOPORT; } if(port > 0){ servaddr.sin_port = htons( (u_short)port ); }else{ fprintf( stderr, "bad port number %s\n", argv[1] ); exit(1); } listenfd = socket(AF_INET, SOCK_STREAM, 0); if(listenfd < 0){ fprintf( stderr, "socket creation failed\n"); exit(1); } if( bind( listenfd, (struct sockaddr *)& servaddr, sizeof(servaddr)) < 0){ fprintf(stderr,"bind failed\n"); exit(1); } if(listen(listenfd, QLEN)<0){ fprintf(stderr,"listen filed\n"); exit(1); } while(1){ alen = sizeof(clientaddr); if((clientfd = accept(listenfd, (struct sockaddr *)& clientaddr, &alen)) < 0){ fprintf(stderr, "accept failed\n"); exit(1); } visits++; sprintf(buf,"this server has been contacted %d time \n", visits); send(clientfd, buf, strlen(buf), 0); close(clientfd); } }
三、实操
1、创建一个文件夹和两个文件(如何创建见Linux基本命令的那篇文章),接着输入上文的代码。
2、在文件夹里打开终端,先输入gcc -v看看虚拟机是否安装gcc,然后输入gcc -o server.out server.c ,最后再输入./server.out 看是否出现闪动的小光标。
3、缩小页面,打开另一个终端,分别输入gcc -o client.out client.c和./client.out,即可实现连接。
四、补充
1、#define是宏定义,PROTOPORT是端口号,5188是自己设定的,后面出现PROTOPORT都用5188来替换。
2、argc表示参数个数,argv表示字符串内容,arg[0]是程序的名称,后面的参数从arg[1]开始都按顺序放入字符串数组中,arg数至少是1个。
3、char buf[1000]表示把想发出去的东西先存下来。
4、memset是清空的意思,malloc后的内存块里面的内容不确定,可能是任意值。
5、servaddr.sin_family = AF_INET表示IPV4,即请IPV4进行网间通信。
6、INADDR_ANY是0.0.0.0,泛指本机的意思,也就是表示本机的所有IP,你可以收到发送到所有有效地址上数据包。
7、SOCK-STREAM连接表示流式套接字,使用TCP协议;SOCK-DGRAM无连接表示数据报套接字,使用UDP协议。
8、accept接受请求,while循环里转一圈,之后继续监听。
9、stderr接收成功后返回新的套接字描述符,和之前那个区分开来。