当前位置:   article > 正文

在Linux系统上实现TCP(socket)通信_linux socket tcp

linux socket tcp

一.什么TCP

TCP(传输控制协议)是一种面向连接的、可靠的、基于字节流的传输层通信协议。

二.TCP通信流程

三. TCP 服务器端  

  1. 1 创建socket
  2. int sockfd = socket(AF_INET, SOCK_STREAM, 0); //SOCK_STREAM tcp通信
  3. 2 绑定(bind)
  4. struct sockaddr_in myaddr;
  5. myaddr.sin_family = AF_INET;
  6. myaddr.sin_port = htons(8888);
  7. myaddr.sin_addr.s_addr = htonl(INADDR_ANY); //INADDR_ANY 自动提取本机ip地址
  8. bind(sockfd, (struct sockaddr *)&myaddr, sizeof(myaddr));
  9. 3 监听 (设置允许同时连接的客户端的最大值 同时连接:已经连上的,不算同时连接)
  10. int listen(int sockfd, int backlog);
  11. listen(sockfd, 5);
  12. 4 阻塞等待连接 accept
  13. int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
  14. 参数:
  15. sockfd :socket 的返回值
  16. addr :客户端的ip地址和端口号存在addr中 (通常为NULL)//udp recvfrom倒数第二个参数一
  17. addrlen :客户端的ip地址和端口号长度 (通常为NULL)//udp recvfrom倒数第一个参数一样
  18. 返回值(重点)
  19. 是一个newfd :(一个新的fd,此fd用来标识客户端,第一个连接的 4,下一个5,....)
  20. 5 接收数据 (阻塞接收)
  21. ssize_t recv(int newfd, void *buf, size_t len, int flags);
  22. 参数: newfd accept的返回值, newfd
  23. buf 接收的数据存放的位置
  24. len 将要接收的数据的长度
  25. flags 暂时为0
  26. 返回值: 实际接收的数据的长度,如果<=0,则证明客户端已经断开连接
  27. 6 发送数据
  28. ssize_t send(int newfd, const void *buf, size_t len, int flags);
  29. 参数: newfd accept的返回值, newfd
  30. buf 发送数据首地址
  31. len 发送数据长度
  32. flags 暂时为0
  33. 返回值: 实际发送的数据的长度
  34. 7 关闭socket
  35. close(newfd);
  36. close(fd);
实例 :
server.c
  1. #include <stdio.h>
  2. #include <sys/socket.h>
  3. #include <netinet/in.h>
  4. int main()
  5. {
  6. int fd = socket(AF_INET, SOCK_STREAM, 0);
  7. struct sockaddr_in myaddr;
  8. myaddr.sin_family = AF_INET;
  9. myaddr.sin_port = htons(8888);
  10. myaddr.sin_addr.s_addr = htonl(INADDR_ANY); //INADDR_ANY 得到当前计算机的ip地址
  11. int ret = bind(fd, (struct sockaddr *)&myaddr, sizeof(myaddr));
  12. printf("ret %d\n",ret);
  13. listen(fd, 5);
  14. int newfd = accept(fd, NULL, NULL); //等待客户端连接
  15. char buf[100] = { 0 };
  16. ret = recv(newfd, buf, sizeof(buf), 0); //newfd 代表连接的客户端
  17. printf("ret %d, newfd is %d, buf is %s\n",ret, newfd, buf);
  18. close(newfd);
  19. close(fd);
  20. }
执行:gcc hello.c -o server      ./server
另外起一个终端,执行:nc 127.0.0.1 8888 ( 模拟出一个客户端 ),在这里发送信息,服务器端就会收到信息。

四. TCP 客户端

  1. 1 创建socket
  2. int sockfd = socket(AF_INET, SOCK_STREAM, 0); //SOCK_STREAM tcp通信
  3. 2 连接服务端
  4. struct sockaddr_in youaddr;
  5. youaddr.sin_family = AF_INET;
  6. youaddr.sin_port = htons(8888);
  7. youaddr.sin_addr.s_addr = inet_addr("127.0.0.1");
  8. int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
  9. 参数:
  10. sockfd socket的返回值
  11. addr 保存对方的ip地址和端口
  12. addrlen sizeof(youaddr);
  13. 返回值:成功 返回0 失败返回 -1
  14. 一旦连接成功,服务端解除阻塞(accpet)
  15. 3 发送数据
  16. ssize_t send(int sockfd, const void *buf, size_t len, int flags);
  17. 参数:
  18. sockfd socket的返回值
  19. buf 发送的数据存放的位置,
  20. len 发送的数据的长度(以字节为单位)
  21. flags 暂时为0
  22. 4 接收数据 //同样用recv()
  23. 5 关闭socket
  24. close(fd);
实例 :
client.c
  1. #include <stdio.h>
  2. #include <sys/socket.h>
  3. #include <netinet/in.h>
  4. int main()
  5. {
  6. int fd = socket(AF_INET, SOCK_STREAM, 0);
  7. struct sockaddr_in youaddr;
  8. youaddr.sin_family = AF_INET;
  9. youaddr.sin_port = htons(8888);
  10. youaddr.sin_addr.s_addr = inet_addr("127.0.0.1");
  11. connect(fd, (struct sockaddr *)&youaddr, sizeof(youaddr));
  12. char buf[] = "hello";
  13. send(fd, buf, sizeof(buf), 0);
  14. close(fd);
  15. }
执行:gcc hello.c -o client      ./client      
另外起一个终端,执行:nc -l 8888(模拟服务器)
之后在执行./client的终端就可以给模拟的服务器发消息了。

五.练习

  实现服务器端循环收数据打印,客户端从 main函数的 参数中提取 ip 地址和端口号 , 可以循环从键盘输入数据,发数据, 如果客户端输入 ‘0’ ,则客户端退出。
server.c   (服务器端)
  1. #include <stdio.h>
  2. #include <sys/socket.h>
  3. #include <netinet/in.h>
  4. int main()
  5. {
  6. int fd = socket(AF_INET, SOCK_STREAM, 0);
  7. struct sockaddr_in myaddr;
  8. myaddr.sin_family = AF_INET;
  9. myaddr.sin_port = htons(8888);
  10. myaddr.sin_addr.s_addr = htonl(INADDR_ANY); //INADDR_ANY 得到当前计算机的ip地址
  11. int ret = bind(fd, (struct sockaddr *)&myaddr, sizeof(myaddr));
  12. listen(fd, 5);
  13. int newfd = accept(fd, NULL, NULL); //等待客户端连接
  14. while(1)
  15. {
  16. char buf[100] = { 0 };
  17. if(recv(newfd, buf, sizeof(buf), 0) > 0) //newfd 代表连接的客户端
  18. printf("buf is %s\n", buf);
  19. else
  20. break;
  21. }
  22. close(fd);
  23. }

client.c   (客户端)

  1. #include <stdio.h>
  2. #include <sys/socket.h>
  3. #include <netinet/in.h>
  4. int main(int argc, char *argv[])
  5. {
  6. int fd = socket(AF_INET, SOCK_STREAM, 0);
  7. struct sockaddr_in youaddr;
  8. youaddr.sin_family = AF_INET;
  9. youaddr.sin_port = htons(atoi(argv[2]));
  10. youaddr.sin_addr.s_addr = inet_addr(argv[1]);
  11. connect(fd, (struct sockaddr *)&youaddr, sizeof(youaddr));
  12. char buf[100] = "hello";
  13. while(1)
  14. {
  15. gets(buf);
  16. if (buf[0] =='0')
  17. {
  18. break;
  19. }
  20. send(fd, buf, sizeof(buf), 0);
  21. }
  22. close(fd);
  23. }

起两个终端一个执行服务器,一个执行客户端。

一个执行:gcc hello.c -o server      ./server

另一个执行:gcc hello.c -o client      ./client    192.168.133.5    8080     
//这里需要输入你的本地IP地址和端口号
这样客户端就能发送消息给服务器,服务器能一直接收消息。(实测成功)

六. 结语

     这就是TCP套接字在Linux上使用的方法与步骤,本次的代码分享到此结束,感谢大家观看,希望大家点点赞,点点关注,后续还会发Linux系统上的TCP并发服务器(服务器能同时连多个客户端),谢谢!
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/天景科技苑/article/detail/896453
推荐阅读
相关标签
  

闽ICP备14008679号