首页 > 代码库 > 第二十三天、二十四天:套接字

第二十三天、二十四天:套接字

  Socket可以看成在两个程序进行通讯连接中的一个端点,一个程序将一段信息写入Socket中,该Socket将这段信息发送给另外一个Socket中,使这段信息能传送到其他程序中。为了区别不同的应用程序进程和连接,许多计算机操作系统为应用程序与TCP/IP协议交互提供了称为套接字(Socket)的接口。

  套接字接口也是进程间通信的一种方式,和前面提到的共享内存、管道通信的区别在于套接字可以提供不同主机之间的通信。

  这次课程主要是要会使用UDP、TCP协议进行通信。使用了两天的时间来学习。可见这个知识点的重要性了。先是写出使用UDP和TCP进行最简单的通信:发送一段字符串。对里面使用到的一些函数再编写,更加的了解函数功能,如 htonl(),htons(),inet_addr(),inet_hton().

  加强的练习包括使用UDP传输大文件以及使用TCP进行网络对话。

先是UDP通信的发送端代码: 

 1 #include<stdio.h> 2 #include<string.h> 3 #include<netinet/in.h> 4 #include<stdlib.h> 5 #include<sys/socket.h> 6 #include<fcntl.h> 7  8 int main() 9 {10     unsigned char data[1024] = {0};11     int ret = read(0,data,1024);12     if(ret < 0){13         perror("read");14         return 1;15     }16     int fd = socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP);17     if(fd < 0){18         perror("socket");19         exit(EXIT_FAILURE);20     }21     struct sockaddr_in mm;22     mm.sin_family = AF_INET;    23     mm.sin_port = htons(9527);24     mm.sin_addr.s_addr = htonl(0xc0a81f72);25      ret = sendto(fd,data,strlen(data),0,(struct sockaddr *)&mm,16);26     if(ret < 0){27         perror("sento");28         exit(EXIT_FAILURE);29     }30     close(fd);31 32 }
UDP通信发送端

UDP通信的接收端代码:

 1 #include<stdio.h> 2 #include<netinet/in.h> 3 #include<stdlib.h> 4 #include<sys/socket.h> 5  6 int main() 7 { 8     int fd = socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP); 9     if(fd < 0){10         perror("socket");11         return 1;12     }13     unsigned char data[1024] = {0};14     struct sockaddr_in mm;15     mm.sin_family = AF_INET;16     mm.sin_port = htons(9527);17     mm.sin_addr.s_addr = htonl(0xc0a81fc8);18     int len = 0;19     int ret = 0;20     ret = bind(fd,(struct sockaddr *)&mm,16);21     if(ret < 0){22         perror("bind");23         return 1;24     }25     struct sockaddr_in gg;26     int gg_len = 0;27     ret = recvfrom(fd,data,1024,0,(struct sockaddr*)&gg,&gg_len);28     if(ret < 0){29         perror("recvfrom");30         return 1;31     }32     printf("data is : %s\n",data);33     close(fd);34 }
UDP通信接收端

  UDP的通信是不可靠的,无连接的数据传输协议。从上面代码看,发送端只管发送数据。不知道接收端是否接送到数据。进行 套接口编程的第一步就是要创建一个套接口,使用socket函数实现。这个函数的三个参数就是指定数据传输的方式、协议。这两个代码要注意的是接收端要对自己的信息进行绑定。

 使用UDP传输大文件发送端:

 1 #include<stdio.h> 2 #include<string.h> 3 #include<sys/socket.h> 4 #include<fcntl.h> 5 #include<netinet/in.h> 6 #include<stdlib.h> 7  8 int main() 9 {                10     11     /*创建套接口*/12     int fd = socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP);13     if(fd < 0){14         perror("socket");15         exit(EXIT_FAILURE);16     }17     /*设置发送目标信息,并发送*/18     int ret = 0;19     char addr[16]= {0};20     printf("please input addr\n");21     ret = read(0,addr,16);22     if(ret < 0){23         perror("read");24         exit(EXIT_FAILURE);25     }26     struct sockaddr_in mm;27     mm.sin_family = AF_INET;28     mm.sin_port =htons(9527);29     mm.sin_addr.s_addr = inet_addr(addr);30     /*将文件保存到字符数组中,发送*/31     int fp = open("aa.tar.gz",O_RDWR);32     if(fp < 0){33         perror("open");34         exit(EXIT_FAILURE);35     }36     char data[1024] = {0};37     int file_size = 0;38     char *file_name ="aa.tar.gz";39     ret = sendto(fd,file_name,20,0,(struct sockaddr *)&mm,16);40     if(ret < 0){41         perror("sento");42         exit(EXIT_FAILURE);43     }44     int sum = 0;45     int i = 0;46     int j = 0;47     while(1){48         file_size = read(fp,data,1024);49         if(file_size < 0){50             perror("read");51             exit(EXIT_FAILURE);52         }53         ret = sendto(fd,data,file_size,0,(struct sockaddr *)&mm,16);54         if(ret < 0){55             perror("sento");56             exit(EXIT_FAILURE);57         }58         printf("file_size is %d\n",file_size);59         sum = sum + file_size;60         if(file_size < 1024){61             printf("sum_size is %d\n",sum);62             break;63         }64         for(i=0;i<100;i++)65             for(j=0;j<1000;j++){66             }67 68     }69     close(fd);70     close(fp);71 }
UDP传输大文件发送端

 使用UDP传输大文件接收端:

 1 #include<stdio.h> 2 #include<string.h> 3 #include<sys/socket.h> 4 #include<fcntl.h> 5 #include<netinet/in.h> 6 #include<stdlib.h> 7  8 int main() 9 {                10     /*创建套接口*/11     int fd = socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP);12     if(fd < 0){13         perror("socket");14         exit(EXIT_FAILURE);15     }16     /*设置接收目标*/17     struct sockaddr_in mm;18     mm.sin_family = AF_INET;19     mm.sin_port =htons(9527);20     mm.sin_addr.s_addr = htonl(0xc0a8010a);21     22     /*绑定,并接收*/23     int ret = bind(fd,(struct sockaddr *)&mm,16);24     if(ret < 0){25         perror("bind");26         exit(EXIT_FAILURE);27     }28     struct sockaddr_in gg;29     int gg_len = 0;30     char data[1024] = {0};31     int recvfile = 0;32     char file_name[20] = {0};33            recvfrom(fd,file_name,20,0,(struct sockaddr *)&gg,&gg_len);34     int  fp = open(file_name,O_RDWR|O_CREAT,0644);35     if(fp < 0){36         perror("open");37         exit(EXIT_FAILURE);38     }39     int sum = 0;40     while(1){41         recvfile = recvfrom(fd,data,1024,0,(struct sockaddr *)&gg,&gg_len);42         if(recvfile < 0){43             perror("recvfrom");44             exit(EXIT_FAILURE);45         }46         ret = write(fp,data,recvfile);47         if(ret < 0){48             perror("write");49             exit(EXIT_FAILURE);50         }51         sum = sum + recvfile;52         if(recvfile < 1024){53         printf("sum_file is %d\n",sum);54             break;55         }56             57     }58     close(fd);59 60 61 }
udp传输大文件接收端

     传输文件的思想很简单。用两个循环,将文件进行连续的传输。写这个程序的时候遇到个问题,就是接收到的文件总是小于发送的。开始以为是UDP的不可靠性造成的。后来经老刘指点。原来是在发送的太快。接收端来不及接收导致的数据流失。在发送的时候延迟一会儿就能过解决问题。

 使用TCP对话服务端:

 1 #include<stdio.h> 2 #include<stdlib.h> 3 #include<string.h> 4 #include<sys/socket.h> 5 #include<netinet/in.h> 6  7 int main() 8 { 9     /*创建套接口*/10     int  fd = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);11     if(fd < 0){12         perror("socket");13         exit(EXIT_FAILURE);14     }15     /*服务端信息*/16     struct sockaddr_in srv;17     srv.sin_family = AF_INET;18     srv.sin_port=htons(9527);19     srv.sin_addr.s_addr = htonl(0xc0a8010a);20     /*绑定*/21     int ret = bind(fd,(struct sockaddr *)&srv,sizeof(struct sockaddr ));22     if(ret < 0){23         perror("bind");24         exit(EXIT_FAILURE);25     }26     /*监听*/27     ret = listen(fd,10);28     if(ret < 0){29         perror("bind");30         exit(EXIT_FAILURE);31     }32     /*接受*/33     struct sockaddr_in snd;34     int snd_len = 0;35     int nfd = accept(fd,(struct sockaddr *)&snd,&snd_len);36     if(nfd < 0){37         perror("accpet");38         exit(EXIT_FAILURE);39     }40     /*聊天*/    41     char data[1024] = {0};42     char revdata[1024] = {0};43     while(1){44         ret = recv(nfd,revdata,1024,0);45         if(ret < 0){46             perror("recv");47             exit(EXIT_FAILURE);48         }49         printf("client say: %s",revdata);50         ret = read(0,data,1024);51         if(ret < 0){52             perror("read");53             exit(EXIT_FAILURE);54         }55         ret = send(nfd,data,1024,0);56         if(ret < 0){57             perror("recv");58             exit(EXIT_FAILURE);59         }60         61     }    62     close(nfd);63     close(fd);64 }
TCP对话服务端

 使用TCP对话客户端:

 1 #include<stdio.h> 2 #include<stdlib.h> 3 #include<string.h> 4 #include<sys/socket.h> 5 #include<netinet/in.h> 6  7 int main() 8 { 9     /*创建套接口*/10     int  fd = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);11     if(fd < 0){12         perror("socket");13         exit(EXIT_FAILURE);14     }15     /*服务端信息*/16     struct sockaddr_in srv;17     srv.sin_family = AF_INET;18     srv.sin_port=htons(9527);19     srv.sin_addr.s_addr = htonl(0xc0a8010a);20     /*链接*/21     int ret = connect(fd,(struct sockaddr *)&srv,sizeof(struct sockaddr ));22     if(ret < 0){23         perror("connect");24         exit(EXIT_FAILURE);25     }26     /*聊天*/27     char data[1024] = {0};28     char revdata[1024] = {0};29     while(1){30         ret = read(0,data,1024);31         if(ret < 0){32             perror("read");33             exit(EXIT_FAILURE);34         }35         ret = send(fd,data,1024,0);36         if(ret < 0){37             perror("send");38             exit(EXIT_FAILURE);39         }40         ret = recv(fd,revdata,1024,0);41         if(ret < 0){42             perror("send");43             exit(EXIT_FAILURE);44         }45         printf("service say: %s",revdata);46     }47     close(fd);48     49 }
使用TCP对话客户端

     TCP传输的实现,就是对三次握手的具体话,服务端和客户端进行连接有着特定的步骤。要会使用lisent、connect、accept这三个函数

 1 #include <stdio.h> 2 #include <string.h> 3 #include <stdlib.h> 4 unsigned long my_inet_addr(char *ipaddr); 5 int main() 6 { 7     char ip[] = "192.168.1.10"; 8     unsigned long oip = my_inet_addr(ip); 9     printf("oip is %x\n",oip);10 }11 unsigned long my_inet_addr(char *ip){12     char *str;    13     char *tmp[4] = {0};14     int i = 0;15 16     do{ 17     str = strstr(ip,".");18     *(tmp+i) = strtok(ip,".");19     ip = str + 1;20     i++;21     }while(str);22 23     return (atoi(*(tmp+0))<< 24 & 0xff000000) |(atoi(*(tmp+1)) << 16 & 0xff0000) |(atoi(*(tmp+2)) << 8 & 0xff00) |(atoi(*(tmp+3)) << 0 & 0xff);24 }
inet_addr实现

  这个函数是ip地址的点分式装换成十六进制输出。思想是先将字符截断。然后转换成字符格式。最后进行移位拼接。

 1 #include<stdio.h> 2 #include<stdlib.h> 3 #include<stdlib.h> 4  5 unsigned char *myinet_ntoa(unsigned long ip){ 6     unsigned char *p = (unsigned char * )&ip; 7     unsigned char *tmp = malloc(20); 8     sprintf(tmp,"%d.%d.%d.%d\0",p[3],p[2],p[1],p[0]); 9     return tmp;10 }11 int main(void)12 {13     unsigned long ip = 0xc0a8010a;14     char *p=myinet_ntoa(ip);15     printf("%s\n",p);16 17 }
inet_nota实现

 

第二十三天、二十四天:套接字