当前位置:   article > 正文

socket网络编程

socket网络编程

网络编程应用于多机通讯,如linux服务器跟安卓手机的通讯,跟ios的手机通讯,跟c51单片绩效的通讯等。

网络编程的要点

1.地址 (由IP地址跟端口号组成)

每个设备都有一个ip地址来标识。

 一台拥有ip地址的主机可以提供许多服务(如web服务,ftp服务等),主机在区分不同的网络服务中显然不能只靠IP地址来区分,还要加上端口号来进行区分。

2.协议(一种数据格式,简单来说就是确定双方交流的语言,不能说一个人讲英语,一个人讲汉语这样双方根本交流不起来)

socket 也叫套接字网络编程主要用 TCP/UDP 的协议 。

TCP/UDP 协议的区别:

TCP面向连接(如打电话你拨号后对方接通建立连接后就可以交流)

UDP是面向报文的(如发短息 ,它只负责发给对方,至于对方看没看到信息它不管)

每一条TCP连接只能点到点的,UDP支持一对一,一对多,多对一,多对多的交互通信

socket网络编程步骤:

 创建套接字

int socket( int domain , int type , int protocol )

 

domain:指明所使用的协议族,一般为AF_INET

type:指定socket的类型,TCP协议是SOCK_STREAM    

protocol:一般为0

 把ip地址和端口号绑定到套接字

int bind(  int sockfd  ,  const struct sockaddr *addr  ,  socklen_t addrlen )

 

sockfd:socket函数返回的文件描述符

addr:含有本机IP地址及端口号等信息的指针

addrlen:一般为sizeof(struct sockaddr_in)

addr 一般都是用 struct sockaddr_in 类型来定义

struct sockaddr_in{
        sa_family_t       sin_family;                 //地址族(Address Family),也就是地址类型
        uint16_t             sin_port;                   //16位的端口号
        struct in_addr   sin_addr;                 //32位IP地址

        char                    sin_zero[8];             //不使用
};

struct in_addr{
        in_addr_t s_addr;    //32位IPv4地址
};

        

sin_portsin_addr 都必须是网络字节序,一般可视化的数字都是主机字节序

htons( )              将端口号由主机字节序转换为网络字节序的整数值。

inet_addr( )        将字符串的IP地址转化为一个网络字节序的整数值。

atoi ( )                 将把​​​​​​​字符串转换成长整型数

监听网络连接

int listen( int sockfd , int backlog )

        

sockfd:socket函数返回的文件描述符

backlog:指定在请求队列中允许的最大请求数

监听到有客户端接入,接受连接

int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);

   

sockfd: socket函数返回的文件描述符     

addr:     是一个指向struct sockaddr *的指针,里面有客户端的IP地址和端口号等信息,如果对客户的地址不感兴趣,那么可以把这个值设置为NULL

addrten:用来接受addr的结构的大小,它指明addr结构所占有的字节个数,同样的,它也可以被设置为NULL。

客户端连接服务器

 int connect( int sockfd , struct sockaddr *serv_addr , int addrlen )

        

sockfd: socket函数返回的文件描述符 

serv_addr:是包含远端主机IP地址和端口号的指针

addrlen:用来接受 serv_addr 的结构的大小,一般为sizeof(struct sockaddr_in)

  • 编写服务器端代码:
  1. #include<stdio.h>
  2. #include <sys/types.h> /* See NOTES */
  3. #include <sys/socket.h>
  4. #include <netinet/in.h>
  5. #include <arpa/inet.h>
  6. #include<string.h>
  7. #include <unistd.h>
  8. #include <stdlib.h>
  9. int main(int argc,char** argv)
  10. {
  11. int s_fd;
  12. int c_fd
  13. struct sockaddr_in s_addr;
  14. struct sockaddr_in c_addr;
  15. if(argc!=3){
  16. printf("argc no 3\n");
  17. exit(-1);
  18. }
  19. s_fd=socket(AF_INET ,SOCK_STREAM ,0);
  20. if(s_fd==-1){
  21. perror("socket");
  22. }
  23. s_addr.sin_family=AF_INET;
  24. s_addr.sin_port=htons(atoi(argv[2]));
  25. s_addr.sin_addr.s_addr=inet_addr(argv[1]);
  26. bind(s_fd,(struct sockaddr *)&s_addr,sizeof(struct sockaddr_in));
  27. listen(s_fd,10);
  28. int len=sizeof(struct sockaddr_in);
  29. c_fd=accept(s_fd,(struct sockaddr *)&c_addr,&len);
  30. if(c_fd==-1){
  31. perror("reason:");
  32. }
  33. puts("connected successfully");
  34. printf("clientIP:%s\n",inet_ntoa(c_addr.sin_addr));
  35. return 0;
  36. }

 服务端代码编写好后,可以在window用 telnet 测试一下是否能连接上

连接成功,并输出 window 的IP地址

  • 编写客户端的代码:
  1. #include<stdio.h>
  2. #include <sys/types.h> /* See NOTES */
  3. #include <sys/socket.h>
  4. #include <netinet/in.h>
  5. #include <arpa/inet.h>
  6. #include <stdlib.h>
  7. int main(int argc,char** argv)
  8. {
  9. int c_fd;
  10. if(argc!=3){
  11. printf("argc no 3\n");
  12. exit(-1);
  13. }
  14. c_fd=socket(AF_INET ,SOCK_STREAM,0);
  15. if(c_fd==-1){
  16. perror("socket");
  17. }
  18. struct sockaddr_in c_addr;
  19. c_addr.sin_family=AF_INET;
  20. c_addr.sin_port=htons(atoi(argv[2]));
  21. s_addr.sin_addr.s_addr=inet_addr(argv[1]);
  22. if(connect(c_fd,(struct sockaddr *)&c_addr,sizeof(struct sockaddr_in))==-1){
  23. perror("connect");
  24. }
  25. return 0;
  26. }

客户端成功连接服务器: 

客户端连接服务器后可以通过 read()和 write()或者 recv() 和 send()等进行数据传送

ssize_t read( int fd , void *buf , size_t count )
ssize_t write( int fd , const void *buf , size_t count )

fd:指定接收端或发送端套接字描述符
buf:指明一个缓冲区,该缓冲区用来存放 read 接收到的数据 或 write 发送的数据
count:指明buf的长度

ssize_t send( int sockfd , const void *buf , size_t len, int flags );
ssize_t recv( int sockfd , void *buf, size_t len , int flags );

fd:指定接收端或发送端套接字描述符
buf:指明一个缓冲区,该缓冲区用来存放 recv 接收到的数据 或 send 发送的数据
len指明buf的长度
flags:指定调用方式,一般置0

以下以read、write 为例

 服务器端:

  1. #include<stdio.h>
  2. #include <sys/types.h> /* See NOTES */
  3. #include <sys/socket.h>
  4. #include <arpa/inet.h>
  5. #include <netinet/in.h>
  6. #include <arpa/inet.h>
  7. #include <unistd.h>
  8. #include <stdlib.h>
  9. #include <string.h>
  10. int main(int argc,char** argv)
  11. {
  12. int s_fd;
  13. int c_fd;
  14. char readbuf[128]={'\0'};
  15. struct sockaddr_in s_addr;
  16. struct sockaddr_in c_addr;
  17. if(argc !=3){
  18. puts("argc no 3");
  19. }
  20. s_fd=socket(AF_INET,SOCK_STREAM,0);
  21. s_addr.sin_family=AF_INET;
  22. s_addr.sin_port=htons(atoi(argv[2]));
  23. s_addr.sin_addr.s_addr=inet_addr(argv[1]);
  24. bind(s_fd,(struct sockaddr *)&s_addr,sizeof(struct sockaddr_in));
  25. listen(s_fd,10);
  26. int len=sizeof(struct sockaddr_in);
  27. c_fd=accept(s_fd,(struct sockaddr *)&c_addr,&len);
  28. puts("connected successfully");
  29. printf("clientIP:%s\n",inet_ntoa(c_addr.sin_addr));
  30. while(1){
  31. read(c_fd,readbuf,sizeof(readbuf));
  32. printf("%s\n",readbuf);
  33. memset(readbuf,0,sizeof(readbuf));
  34. }
  35. return 0;
  36. }

客户端:

  1. #include<stdio.h>
  2. #include <sys/types.h> /* See NOTES */
  3. #include <sys/socket.h>
  4. #include <netinet/in.h>
  5. #include <arpa/inet.h>
  6. #include <stdlib.h>
  7. #include <unistd.h>
  8. # include <string.h>
  9. int main(int argc,char** argv)
  10. {
  11. int c_fd;
  12. int n_write;
  13. char writebuf[128]={'\0'};
  14. struct sockaddr_in c_addr;
  15. if(argc!=3){
  16. printf("argc no 3\n");
  17. exit(-1);
  18. }
  19. c_fd=socket(AF_INET ,SOCK_STREAM,0);
  20. if(c_fd==-1){
  21. perror("socket");
  22. }
  23. c_addr.sin_family=AF_INET;
  24. c_addr.sin_port=htons(atoi(argv[2]));
  25. s_addr.sin_addr.s_addr=inet_addr(argv[1]);
  26. if(connect(c_fd,(struct sockaddr *)&c_addr,sizeof(struct sockaddr_in))==-1){
  27. perror("connect");
  28. }
  29. while(1){
  30. puts("input");
  31. scanf("%s",writebuf);
  32. n_write=write(c_fd,writebuf,strlen(writebuf));
  33. if(n_write==-1){
  34. puts("write failed");
  35. exit(-1);
  36. }
  37. }
  38. return 0;
  39. }

数据传送成功:

当要把接收到的数据用 printf()进行输出时不要忘了加\n 否则会输出不正常.

声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:【wpsshop博客】
推荐阅读
相关标签
  

闽ICP备14008679号