TCP十一个面向连接的网络协议,数据传输前必须先建立连接
即客户端和服务器之间需要有一个规则来相互约束。
两者之间的通信可以如下所示
1 建立socket套接口
2 bind函数 绑定端口和IP
3 调用listen函数监听客户端发过来的请求
4 客户端建立socket套接口
5客户端用connect函数连接远程服务器ip端口
6服务器用accept函数接受客户端的请求,建立起通信连接
7建立起连接以后客户端可以用write函数(或者send函数)往socket服务器端发送数据,也可以用read函数(或者recv函数)读取客户端发送过来的数据
8服务器端可以用read函数(recv函数)读取客户端发送过来的数据,也可以用write函数(send函数)往客户端发送数据
9 通信完成以后用close关闭socket连接
服务器端程序如下所示:
<span style="font-size:18px;">#include <stdlib.h> #include <stdio.h> #include <errno.h> #include <string.h> #include <netdb.h> #include <sys/types.h> #include <netinet/in.h> #include <sys/socket.h> #include <unistd.h> #define MAXSIZE 1024 /*定义数据缓冲区大小*/ int main(int argc, char *argv[]) { int sockfd,new_fd; struct sockaddr_in server_addr; /*定义服务器端套接口数据结构server_addr */ struct sockaddr_in client_addr; /*定义客户端套接口数据结构client_addr */ int sin_size,portnumber; char buf[MAXSIZE]; /*发送数据缓冲区*/ if(argc!=2) { fprintf(stderr,"Usage:%s portnumber\a\n",argv[0]); exit(1); } if((portnumber=atoi(argv[1]))<0) { /*获得命令行的第二个参数--端口号,atoi()把字符串转换成整型数*/ fprintf(stderr,"Usage:%s portnumber\a\n",argv[0]); exit(1); } if((sockfd=socket(AF_INET,SOCK_STREAM,0))==-1) /*服务器端开始建立socket描述符*/ { fprintf(stderr,"Socket error:%s\n\a",strerror(errno)); exit(1); } /*服务器端填充 sockaddr结构*/ bzero(&server_addr,sizeof(struct sockaddr_in)); /*先将套接口地址数据结构清零*/ server_addr.sin_family=AF_INET; server_addr.sin_addr.s_addr=htonl(INADDR_ANY); server_addr.sin_port=htons(portnumber); if(bind(sockfd,(struct sockaddr *)(&server_addr),sizeof(struct sockaddr))==-1) /*调用bind函数绑定端口*/ { fprintf(stderr,"Bind error:%s\n\a",strerror(errno)); exit(1); } if(listen(sockfd,5)==-1) /*端口绑定成功,监听sockfd描述符,同时处理的最大连接请求数为5 */ { fprintf(stderr,"Listen error:%s\n\a",strerror(errno)); exit(1); } while(1) /*服务器阻塞,等待接收连接请求,直到客户程序发送连接请求*/ { sin_size=sizeof(struct sockaddr_in); if((new_fd=accept(sockfd,(struct sockaddr *)(&client_addr),&sin_size))==-1) /*调用accept接受一个连接请求*/ { fprintf(stderr,"Accept error:%s\n\a",strerror(errno)); exit(1); } fprintf(stderr,"Server get connection from %s\n",inet_ntoa(client_addr.sin_addr)); /*TCP连接已建立,打印申请连接的客户机的IP地址*/ printf("Connected successful, please input the masage[<1024 bytes]:\n"); /*提示用户输入将要发送的数据,长度小于缓冲区的长度,即1024字节*/ if(fgets(buf, sizeof(buf), stdin) != buf) { /*从终端输入的数据存放在buf缓冲区*/ printf("fgets error!\n"); exit(1); } if(write(new_fd,buf,strlen(buf))==-1) /*调用write发送数据*/ { fprintf(stderr,"Write Error:%s\n",strerror(errno)); exit(1); } close(new_fd); /*本次通信已结束,关闭客户端的套接口,并循环下一次等待*/ } close(sockfd); /*服务器进程结束,关闭服务器端套接口*/ exit(0); } </span>
客户端程序如下
<span style="font-size:18px;">#include <stdlib.h> #include <stdio.h> #include <errno.h> #include <string.h> #include <netdb.h> #include <sys/types.h> #include <netinet/in.h> #include <sys/socket.h> int main(int argc, char *argv[]) { int sockfd; char buffer[1024]; struct sockaddr_in server_addr; /*定义服务器端套接口数据结构server_addr */ struct hostent *host; int portnumber,nbytes; if(argc!=3) { fprintf(stderr,"Usage:%s hostname portnumber\a\n",argv[0]); exit(1); } if((host=gethostbyname(argv[1]))==NULL) { /*获得命令行的第二个参数-主机名*/ fprintf(stderr,"Gethostname error\n"); exit(1); } if((portnumber=atoi(argv[2]))<0) { /*获得命令行的第三个参数--端口号,atoi()把字符串转换成整型数*/ fprintf(stderr,"Usage:%s hostname portnumber\a\n",argv[0]); exit(1); } /* 客户程序开始建立 sockfd描述符 */ if((sockfd=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(sockfd,(struct sockaddr *)(&server_addr),sizeof(struct sockaddr))==-1) { fprintf(stderr,"Connect Error:%s\a\n",strerror(errno)); exit(1); } /*连接成功,调用read读取服务器发送来的书籍*/ if((nbytes=read(sockfd,buffer,1024))==-1) { fprintf(stderr,"Read Error:%s\n",strerror(errno)); exit(1); } buffer[nbytes]='\0'; printf("I have received:%s\n",buffer); /*输出接收到的数据*/ close(sockfd); /*结束通信*/ exit(0); } </span>
在终端编译链接程序
gcc -o server server.c
gcc -o cilent client.c
在一个终端下面输入 ./server 5678
在另一个终端中输入 ./cilent localhost 5678
可以在服务器端看到一些提示
并且在服务器端输入一些 信息 I like
然后在客户端可以收到服务器端输入的 I like 信息