基于TCP的C/S程序设计
1算法流程:

2代码及注释:
server.c
#include<stdio.h> #include<string.h> #include<unistd.h> #include<stdlib.h> #include<netinet/in.h> #include<sys/socket.h> #include<arpa/inet.h> #define CHARNUM 100 int main() { int sockfd,connfd,n; char send_buf[CHARNUM],recv_buf[CHARNUM],addr[INET_ADDRSTRLEN]; struct sockaddr_in server_addr,client_addr; socklen_t client_addr_len; sockfd=socket(AF_INET,SOCK_STREAM,0);//建立一个套接字 bzero(&server_addr,sizeof(server_addr));//清空地址 server_addr.sin_addr.s_addr=htonl(INADDR_ANY);//地址为0.0.0.0 server_addr.sin_family=AF_INET; server_addr.sin_port=htons(8000);//端口8000 bind(sockfd,(struct sockaddr *)&server_addr,sizeof(server_addr));//将地址与套接字捆绑 listen(sockfd,10);//监听申请的连接 printf("WAIT...\n"); while(1) { client_addr_len=sizeof(client_addr); connfd=accept(sockfd,(struct sockaddr *)&client_addr,&client_addr_len);//套接字接受的一个连接 if(connfd>0) { printf("client's IP:%s\n",inet_ntop(AF_INET,&client_addr.sin_addr,addr,INET_ADDRSTRLEN)); break; } } while(1) { n=read(connfd,recv_buf,CHARNUM);//接收数据 printf("client say:%s\n",recv_buf); if(strcmp(recv_buf,"quit")==0) { printf("client exited!"); break; } printf("reply:"); scanf("%s",send_buf); if(strcmp(send_buf,"quit")==0) { strcpy(send_buf,"SERVER CLOSED!"); write(connfd,send_buf,20); break; } write(connfd,send_buf,100);//发送数据 } printf("server is closed!\n"); close(sockfd);关闭链接 return 0; }
client.c
#include<stdio.h> #include<stdlib.h> #include<string.h> #include<unistd.h> #include<sys/socket.h> #include<netinet/in.h> #define CHARNUM 100 int main() { int sockfd,n; struct sockaddr_in server_addr,client_addr; char send_buf[CHARNUM],recv_buf[CHARNUM],addr[INET_ADDRSTRLEN]; sockfd=socket(AF_INET,SOCK_STREAM,0); bzero(&server_addr,sizeof(server_addr)); server_addr.sin_family=AF_INET; server_addr.sin_addr.s_addr=htonl(INADDR_ANY); server_addr.sin_port=htons(8000); connect(sockfd,(struct sockaddr*)&server_addr,sizeof(server_addr));//建立与指定socket的连接 while(1) { printf("send to server:"); scanf("%s",send_buf); write(sockfd,send_buf,CHARNUM); if(strcmp(send_buf,"quit")==0) { printf("CLOSED!\n"); break; } n=read(sockfd,recv_buf,CHARNUM); if(strcmp(recv_buf,"SERVER CLOSED!")==0) { printf("SERVER CLOSED!\n"); break; } printf("server:%s\n",recv_buf); } close(sockfd); return 0; }
3效果:


4代码中所用系统调用与结构体说明:
htonl()
将主机数转换成无符号长整型的网络字节顺序。本函数将一个32位数从主机字节顺序转换成网络字节顺序。
INADDR_ANY就是指定地址为0.0.0.0的地址。
htons是将整型变量从主机字节顺序转变成网络字节顺序。
需要注意的是:
sockaddr和sockaddr_in二者的占用的内存大小是一致的,因此可以互相转化,从这个意义上说,他们并无区别。
sockaddr常用于bind、connect、recvfrom、sendto等函数的参数,指明地址信息。是一种通用的套接字地址。而sockaddr_in 是internet环境下套接字的地址形式。所以在网络编程中我们会对sockaddr_in结构体进行操作。使用sockaddr_in来建立所需的信息,最后使用类型转化就可以了。

浙公网安备 33010602011771号