实验5 基本套接字实验 |
要掌握的函数: 2.1 函数 int socket(int domain,int type,int protocol) 一般情况下使用: socket(AF_INET,SOCK_STREAM,0); 返回的是socket 套接字的编号 2.2 数据类型: struct sockaddr_in(表示IP 地址和端口号) 有三个重要的域: sin_family sin_port sin_addr 每次必须设置 例如程序 memset(&server_addr,0,sizeof(server_addr)); server_addr.sin_family=AF_INET; server_addr.sin_addr.s_addr=htonl(INADDR_ANY); server_addr.sin_port=htons(81); 将地址设为0.0.0.0 将端口设置为81,采用协议是互联网协议 2.3 函数bind 通常使用 bind(sockfd,(struct sockaddr*)(&server_addr),sizeof(server_addr)); 第一个参数是绑定的套接字编号,第二个是要绑定的地址的指针,第三个地址结 构体大小,这样把一个套接字和一个IP 地址+端口绑定了 |
2.4 函数listen 通常情况listen(sockfd,128);监听某个套接字(绑定的),阻塞,如果有客户端对 我进行连接,则阻塞停止进入下一步程序运行。 |
2.5 函数accept 通常使用: newfd=accept(sockfd,(struct sockaddr*)(&client_addr),&size); 第一个参数为刚刚从监听中的那个套接字编号,第二个参数为客户的地址结构体 的地址(这个实际是一个输出参数),第三个参数是地址结构体的大小(也是输出 参数),这是系统根据受到的TCP 包的头字节进行填充的。 返回值很重要,是一个新的套接字编号。事实上以后通过这个套接字进行通信了。 |
2.6 客户端函数: connect(sockfd,(struct sockaddr*)(&addr), sizeof (addr)); 注意addr 其实是一个服务器的sockaddr_in 类型 2.7 读函数 read(new_fd,buf,BUFSIZE); 第一个参数是新的套接字编号 |
第二个参数是缓冲区起始地址 第三个是缓冲区大小 把套接字受到的内容写道缓冲区中 2.8 写函数 write(new_fd,buf,BUFSIZE); 第一个参数是新的套接字编号 第二个参数是缓冲区起始地址 第三个是缓冲区大小 把缓冲区的内容送到套接字中(逻辑上就是送到网络中) ×××××××××××××××××××××××× 服务器的过程 1 socket 函数产生监听套接字 2 设置地址结构体(sockaddr_int)的监听地址(0.0.0.0)和端口(例如82) 和协议 族(AF_INET) 3 将地址结构体和监听套接字绑定 4 调用listen,等待客户端的连接 5 当客户端有连接时(listen) 6 调用accept() 返回出新的套接字,作为读写套接字,并且填充了客户地址结 构体 accept(sockfd,(struct sockaddr*)(&client_addr),&size); 7 读客户端发来的信息read(newfd,buf,BUFSIZE) 客户端过程的第3 步 8 分析读的信息,写信息到套接字中 |
×××××××××××××××××××××××× 客户端过程: 1 socket 函数产生连接套接字 2 设置地址结构体(sockaddr_int)的连接的地址(127.0.0.1)和端口(例如82) 和 协议族(AF_INET) 3 连接服务器connct() 例如connect(sockfd,(struct sockaddr*)(&server_addr),sizeof server_addr); 4 写套接字write(sockfd,buf,strlen(buf)) 5 读套接字read(sockfd,buf,BUFSIZE) ×××××××××××××××××××××××× |
简单服务器: #include <stdio.h> #include <stdlib.h> #include <errno.h> #include <string.h> #include <sys/socket.h> #include <sys/types.h> #include <arpa/inet.h> |
#define BUFSIZE 128 #define PORT 82 char buf[BUFSIZE+1]; int main() { int sockfd; int new_fd; struct sockaddr_in server_addr; struct sockaddr_in client_addr; |
socklen_t size; |
//创建服务器监听套接字 sockfd=socket(AF_INET,SOCK_STREAM,0); if(sockfd==-1){fprintf(stderr,"socket error:%s",strerror(errno)); exit(-1);} |
//为监听套接字准备IP 地址和端口号 memset(&server_addr,0,sizeof(server_addr)); server_addr.sin_family=AF_INET; server_addr.sin_addr.s_addr=htonl(INADDR_ANY); server_addr.sin_port=htons(PORT); |
//将监听套接字绑定到地址和端口上 int bret=bind(sockfd,(struct sockaddr*)(&server_addr),sizeof(server_addr)); if(bret==-1) {fprintf(stderr,"bind error %s\r\n",strerror(errno));exit(-1);}; |
//监听 int lret=listen(sockfd,128); if(lret==-1) {fprintf(stderr,"listen error %s\r\n",strerror(errno));exit(-1);}; |
while(1) { size=sizeof(struct sockaddr_in); //接收客户端连接并且创建服务器连接套接字 new_fd=accept(sockfd,(struct sockaddr*)(&client_addr),&size); if(new_fd==-1) {fprintf(stderr,"accept error %s\r\n",strerror(errno));exit(-1);}; |
printf("\r\nServergotanconnection %s:%d\r\n",inet_ntoa(client_addr.sin_addr),ntohs(client_addr.sin_port)); |
from |
//循环读入客户端发来的消息 for(;;) { |
int z=read(new_fd,buf,BUFSIZE); |
if(z<0) {fprintf(stderr,"listen error %s\r\n",strerror(errno));exit(-1);}; if(z==0) {printf("client quit! \r\n");;break;} buf[z]=0; //打印buf 中的内容,注意一定要打印\r\n 否则放在缓冲区出不来 printf("%s\r\n",buf); } } } |
简单服务器的客户端程序: #include <stdio.h> #include <stdlib.h> #include <errno.h> #include <string.h> #include <sys/socket.h> #include <sys/types.h> #include <arpa/inet.h> #include <unistd.h> #include <netdb.h> #define PORT 82 #define BUFSIZE 128 char buf[BUFSIZE+1]; int main() { int sockfd; int new_fd; struct sockaddr_in server_addr; struct sockaddr_in client_addr; |
//创建客户端套接字 sockfd=socket(AF_INET,SOCK_STREAM,0); if(sockfd==-1){fprintf(stderr,"socket error:%s",strerror(errno)); exit(-1);} |
//创建服务器地址和端口号结构体 memset(&server_addr,0,sizeof(server_addr)); server_addr.sin_family=AF_INET; inet_aton("127.0.0.1",&server_addr.sin_addr); |
server_addr.sin_port=htons(PORT); |
printf("\r\nip地址:%s端 %d\r\n",inet_ntoa(server_addr.sin_addr),ntohs(server_addr.sin_port)); |
口 |
: |
//连接服务器 int cret=connect(sockfd,(struct sockaddr*)(&server_addr),sizeof server_addr); if(cret==-1) {fprintf(stderr,"connect error:%s",strerror(errno)); exit(-1);} |
printf("\r\n conncet to Server |
for(;;) { |
%s\r\n",inet_ntoa(server_addr.sin_addr)); |
scanf("%s",buf);//键盘输入 if(!strcasecmp(buf,"QUIT")) {printf("end client");break;}; int z=write(sockfd,buf,strlen(buf)); if(z<0){fprintf(stderr,"write error:%s",strerror(errno)); exit(-1);} printf("client has sent %s to the server \r\n",buf); }// end of for } 回文的服务器 当客户端输入1,则服务器将当前时间发送给客户端 当客户端输入2,则服务器将hello 发送给客户端 当客户端输入其他,则服务器将其回文发送给客户端 #include <stdio.h> #include <stdlib.h> #include <errno.h> #include <string.h> #include <sys/socket.h> #include <sys/types.h> #include <arpa/inet.h> #include <time.h> |
#define BUFSIZE 128 #define PORT 82 char buf[BUFSIZE+1]; |
void back(char *s) { int i=0; int len=strlen(s); |
for(;i<len/2;i++) { char temp=s[i]; s[i]=s[len-1-i]; s[len-1-i]=temp; } } |
int main() { int sockfd; int new_fd; struct sockaddr_in server_addr; struct sockaddr_in client_addr; |
socklen_t size; |
//创建服务器监听套接字 sockfd=socket(AF_INET,SOCK_STREAM,0); if(sockfd==-1){fprintf(stderr,"socket error:%s",strerror(errno)); exit(-1);} |
//为监听套接字准备IP 地址和端口号 memset(&server_addr,0,sizeof(server_addr)); server_addr.sin_family=AF_INET; server_addr.sin_addr.s_addr=htonl(INADDR_ANY); server_addr.sin_port=htons(PORT); |
//将监听套接字绑定到地址和端口上 int bret=bind(sockfd,(struct sockaddr*)(&server_addr),sizeof(server_addr)); if(bret==-1) {fprintf(stderr,"bind error %s\r\n",strerror(errno));exit(-1);}; |
//监听 int lret=listen(sockfd,128); if(lret==-1) {fprintf(stderr,"listen error %s\r\n",strerror(errno));exit(-1);}; |
while(1) { size=sizeof(struct sockaddr_in); //接收客户端连接并且创建服务器连接套接字 new_fd=accept(sockfd,(struct sockaddr*)(&client_addr),&size); if(new_fd==-1) |
{fprintf(stderr,"accept error %s\r\n",strerror(errno));exit(-1);}; |
printf("\r\nServergotanconnection %s:%d\r\n",inet_ntoa(client_addr.sin_addr),ntohs(client_addr.sin_port)); |
//循环读入客户端发来的消息 for(;;) { |
int z=read(new_fd,buf,BUFSIZE); |
if(z<0) {fprintf(stderr,"listen error %s\r\n",strerror(errno));exit(-1);}; if(z==0) {printf("client quit! \r\n");;break;} buf[z]=0; //打印buf 中的内容,注意一定要打印\r\n 否则放在缓冲区出不来 printf("%s\r\n",buf); //回应文 time_t now=time(NULL); //printf("debug1: %d %s %d",new_fd,buf,strlen(buf)); if(strcasecmp(buf,"1")==0) sprintf(buf,"%s",ctime(&now)); else if(strcasecmp(buf,"2")==0) { sprintf(buf,"%s","hello world!"); } else back(buf); z= write(new_fd,buf,strlen(buf)); if(z<0){fprintf(stderr,"listen error %s\r\n",strerror(errno));exit(-1);}; |
} |
} |
} 回文的客户端程序: #include <stdio.h> #include <stdlib.h> #include <errno.h> #include <string.h> #include <sys/socket.h> #include <sys/types.h> #include <arpa/inet.h> #include <unistd.h> #include <netdb.h> #define PORT 82 |
from |
#define BUFSIZE 128 char buf[BUFSIZE+1]; int main() { int sockfd; int new_fd; struct sockaddr_in server_addr; struct sockaddr_in client_addr; |
struct hostent *host;//需要netdb.h,报错特别奇怪不会怀疑到没有include netdb.h //建立host //创建客户端套接字 sockfd=socket(AF_INET,SOCK_STREAM,0); if(sockfd==-1){fprintf(stderr,"socket error:%s",strerror(errno)); exit(-1);} |
//创建服务器地址和端口号结构体 memset(&server_addr,0,sizeof(server_addr)); server_addr.sin_family=AF_INET; inet_ntoa("127.0.0.1", &server_addr.sin_addr); server_addr.sin_port=htons(PORT); |
printf("\r\n ip 地址:%s 端口:%d\r\n", inet_ntoa(server_addr.sin_addr), ntohs(server_addr.sin_port)); //连接服务器 int cret=connect(sockfd,(struct sockaddr*)(&server_addr),sizeof server_addr); if(cret==-1) {fprintf(stderr,"connect error:%s",strerror(errno)); exit(-1);} |
printf("\r\n conncet to Server %s\r\n",inet_ntoa(server_addr.sin_addr)); for(;;) { scanf("%s",buf);//键盘输入 if(!strcasecmp(buf,"QUIT")) {printf("end client");break;} int z=write(sockfd,buf,strlen(buf)); if(z<0){fprintf(stderr,"write error:%s",strerror(errno)); exit(-1);} printf("client has sent %s to the server \r\n",buf); }// end of for |
} |
并发服务器(多进程) |
#include <stdio.h> |
#include <stdlib.h> #include <errno.h> #include <string.h> #include <sys/socket.h> #include <sys/types.h> #include <arpa/inet.h> #include <time.h> |
#define BUFSIZE 128 #define PORT 82 char buf[BUFSIZE+1]; |
void back(char *s) { |
int i=0; int len=strlen(s); for(;i<len/2;i++) { char temp=s[i]; s[i]=s[len-1-i]; s[len-1-i]=temp; } |
} int main() { int sockfd; int new_fd; struct sockaddr_in server_addr; struct sockaddr_in client_addr; |
socklen_t size; |
//创建服务器监听套接字 sockfd=socket(AF_INET,SOCK_STREAM,0); if(sockfd==-1){fprintf(stderr,"socket error:%s",strerror(errno)); exit(-1);} |
//为监听套接字准备IP 地址和端口号 memset(&server_addr,0,sizeof(server_addr)); server_addr.sin_family=AF_INET; server_addr.sin_addr.s_addr=htonl(INADDR_ANY); server_addr.sin_port=htons(PORT); |
//将监听套接字绑定到地址和端口上 |
int bret=bind(sockfd,(struct sockaddr*)(&server_addr),sizeof(server_addr)); if(bret==-1) {fprintf(stderr,"bind error %s\r\n",strerror(errno));exit(-1);}; |
//监听 int lret=listen(sockfd,128); if(lret==-1) {fprintf(stderr,"listen error %s\r\n",strerror(errno));exit(-1);}; |
while(1) { size=sizeof(struct sockaddr_in); //接收客户端连接并且创建服务器连接套接字 new_fd=accept(sockfd,(struct sockaddr*)(&client_addr),&size); if(new_fd==-1) {fprintf(stderr,"accept error %s\r\n",strerror(errno));exit(-1);}; |
printf("\r\nServergotanconnection %s:%d\r\n",inet_ntoa(client_addr.sin_addr),ntohs(client_addr.sin_port)); int ret=fork(); if(ret==0) { //循环读入客户端发来的消息 for(;;) { |
int z=read(new_fd,buf,BUFSIZE); |
if(z<0) {fprintf(stderr,"listen error %s\r\n",strerror(errno));exit(-1);}; if(z==0){printf("client%s:%dquit!process %d\r\n",inet_ntoa(client_addr.sin_addr),htons(client_addr.sin_port),getpid());;exit(0); } buf[z]=0; //打印buf 中的内容,注意一定要打印\r\n 否则放在缓冲区出不来 printf("process%ugetmessagefromclient%s%d %s\r\n",getpid(),inet_ntoa(client_addr.sin_addr),ntohs(client_addr.sin_port),buf); //回应文 time_t now=time(NULL); |
if(strcasecmp(buf,"1")==0) sprintf(buf,"%s",ctime(&now)); else if(strcasecmp(buf,"2")==0) { |
from |
sprintf(buf,"%s","hello world!"); |
} else back(buf); z= write(new_fd,buf,strlen(buf)); if(z<0){fprintf(stderr,"listen error %s\r\n",strerror(errno));exit(-1);}; } } |
} |
} |
转载于:https://blog.51cto.com/wolfword/1240341