[关闭]
@Dubyoo 2014-06-13T20:47:20.000000Z 字数 4956 阅读 2939

2014-04-04 Linux网络编程 - socket建立TCP连接

使用TCP协议的流程

  1. 服务端:socket -> bind -> listen -> accept -> recv -> send -> close
  2. 客户端:socket ------------------> connect -> send -> recv -> close

1.socket

  1. /* socket:生成一个套接口描述符 */
  2. int socket(int domain, int type, int protocol);
  3. //domain ---> AF_INET: IPv4; AF_INET6: IPv6;
  4. //type ---> SOCK_STREAM: tcp; SOCK_DGRAM: udp;
  5. //protocol ---> 指定socket传输所用的协议编号,通常为0 。
  6. /*返回值:成功则返回套接口描述符,失败返回-1*/

2.bind

  1. /* bind:绑定一个端口号和ip地址,使套接口与端口号和ip地址相关联 */
  2. int bind(int sockfd, struct sockaddr * my_addr, int addrlen);
  3. // sockfd为前面socket的返回值。
  4. // my_addr为结构体指针变量,结构体如下
  5. // addrlen:sockaddr的结构体长度。通常是sizeof(struct sockaddr);
  6. /*返回值:成功则返回0,失败返回-1*/
  1. /*结构体*/
  2. struct sockaddr //此结构体不常用
  3. {
  4. unsigned short int sa_family; //调用socket()时的domain参数,即AF_INET值。
  5. char sa_data[14]; //最多使用14个字符长度
  6. };
  7. //使用ipv4时,其socketaddr结构定义便为
  8. struct sockaddr_in //常用的结构体
  9. {
  10. unsigned short int sin_family; //即为sa_family AF_INET
  11. uint16_t sin_port; //为使用的port编号
  12. struct in_addr sin_addr; //为IP 地址
  13. unsigned char sin_zero[8]; //未使用
  14. };
  15. struct in_addr
  16. {
  17. uint32_t s_addr;
  18. };
  1. /*bind实例*/
  2. struct sockaddr_in my_addr; //定义结构体变量
  3. memset(&my_addr, 0, sizeof(struct sockaddr)); //将结构体清空
  4. //或bzero(&my_addr, sizeof(struct sockaddr));
  5. my_addr.sin_family = AF_INET; //表示采用Ipv4网络协议
  6. my_addr.sin_port = htons(8888);
  7. //表示端口号为8888,通常是大于1024的一个值。
  8. //htons()用来将参数指定的16位hostshort转换成网络字符顺序
  9. my_addr.sin_addr.s_addr = inet_addr("192.168.1.13");
  10. // inet_addr()用来将IP地址字符串转换成网络所使用的二进制数字,如果为INADDR_ANY,这表示服务器自动填充本机IP地址。
  11. int iret = bind(sfd, (struct sockaddr*)&my_str, sizeof(struct socketaddr));
  12. if(iret == -1)
  13. {
  14. perror("bind");
  15. close(sfd);
  16. exit(-1);
  17. }

注:
my_addr.sin_port 置为 0,函数会自动为你选择一个未占用的端口来使用。
my_addr.sin_addr.s_addr 置为 INADDR_ANY,系统会自动填入本机IP地址。


3.listen

  1. /* 使服务器的这个端口和IP处于监听状态,等待网络中某一客户机的连接请求。如果客户端有连接请求,端口就会接受这个连接 */
  2. int listen(int sockfd, int backlog);
  3. //sockfd: socket描述符
  4. //backlog: 指定同时能处理的最大连接要求,通常为10或者5。 最大值可设至128
  5. /*返回值:成功则返回0,失败返回-1*/

4.accept

  1. /*接受远程计算机的连接请求,建立起与客户机之间的通信连接*/
  2. int accept(int sockfd, struct sockaddr * addr, int * addrlen);
  3. //sockfd: socket描述符
  4. //addr: 系统会把远程客户端主机的信息(地址和端口号信息)保存到这个指针所指的结构体中
  5. //addrlen: 表示结构体的长度,为整型指针
  6. /*返回值:成功则返回新的客户端socket描述符new_fd,失败返回-1*/

5.recv

  1. /* 用新的套接字来接收远端主机传来的数据,并把数据存到由参数buf 指向的内存空间 */
  2. int recv(int sockfd,void *buf,int len,unsigned int flags);
  3. //sockfd: socket描述符
  4. //buf: 接收的字符串存入缓冲区buf中
  5. //len: 缓冲区长度
  6. //flags: 通常为0
  7. /*返回值:成功则返回实际接收到的字符数,可能会少于你所指定的接收长度。失败返回-1*/

6.send

  1. /* 发送消息到指定IP */
  2. int send(int s,const void * msg,int len,unsigned int flags);
  3. //sockfd: socket描述符
  4. //msg: 一般为常量字符串,发出的消息
  5. //len: msg长度
  6. //flags: 通常为0
  7. /*返回值:成功则返回实际传送出去的字符数,可能会少于你所指定的发送长度。失败返回-1*/

7.close

  1. close(sock_fd) ;

8.connect (in client)

  1. /*用来请求连接远程服务器,将参数sockfd 的socket 连至参数serv_addr 指定的服务器IP和端口号上去*/
  2. int connect(int sockfd,struct sockaddr * serv_addr,int addrlen);
  3. //sockfd: socket描述符
  4. //serv_addr: 结构体指针变量,存储着远程服务器的IP与端口号信息
  5. //addrlen: 结构体变量的长度
  6. /*返回值:成功则返回0,失败返回-1*/
  1. /*connect实例*/
  2. struct sockaddr_in seraddr; //请求连接服务器
  3. memset(&seraddr, 0, sizeof(struct sockaddr));
  4. seraddr.sin_family = AF_INET;
  5. seraddr.sin_port = htons(8888); //服务器的端口号
  6. seraddr.sin_addr.s_addr = inet_addr("192.168.0.101"); //服务器的ip
  7. if(connect(sfd, (struct sockaddr*)&seraddr, sizeof(struct sockaddr)) == -1)
  8. {
  9. perror("connect");
  10. close(sfd);
  11. exit(-1);
  12. }

实例

  1. /*tcp_server.c*/
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #include <string.h>
  5. #include <netinet/in.h>
  6. #include <sys/socket.h>
  7. #include <arpa/inet.h>
  8. #include <unistd.h>
  9. #include <sys/types.h>
  10. int main(int argc, char* argv[]) // ---> ./exe [port]
  11. {
  12. //1.socket
  13. int fd_server ,fd_client;
  14. if(-1 == (fd_server= socket(AF_INET,SOCK_STREAM, 0)))
  15. {
  16. perror("socket");
  17. exit(-1);
  18. }
  19. //2.bind
  20. struct sockaddr_in server_addr ;
  21. memset(&server_addr, 0, sizeof(server_addr));
  22. server_addr.sin_family = AF_INET ;
  23. server_addr.sin_port = htons(atoi(argv[1]));
  24. server_addr.sin_addr.s_addr = INADDR_ANY ;
  25. if(0 != bind(fd_server, (struct sockaddr*)&server_addr, sizeof(server_addr)))
  26. {
  27. perror("bind");
  28. close(fd_server);
  29. exit(-1);
  30. }
  31. //3.listen
  32. if(-1 == listen(fd_server, 5))
  33. {
  34. perror("listen");
  35. close(fd_server);
  36. exit(-1);
  37. }
  38. //accept
  39. struct sockaddr_in client_addr ;
  40. memset(&client_addr, 0, sizeof(client_addr));
  41. int len = sizeof(client_addr);
  42. fd_client = accept(fd_server, (struct sockaddr*)&client_addr, &len);
  43. printf("ip: %s:%d connection establited !\n",inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port) );
  44. //4.recv
  45. char buf[128] ;
  46. int iret = recv(fd_client, buf, 128, 0);
  47. buf[iret] = '\0';
  48. write(1, buf, strlen(buf));
  49. //5.send
  50. memset(buf, 0, 128);
  51. strcpy(buf, "I am the server, your msg has been received !\n");
  52. send(fd_client, buf, strlen(buf), 0);
  53. //6.close
  54. close(fd_server);
  55. close(fd_client);
  56. return 0 ;
  57. }
  1. /*tcp_client.c*/
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #include <string.h>
  5. #include <netinet/in.h>
  6. #include <sys/socket.h>
  7. #include <arpa/inet.h>
  8. #include <unistd.h>
  9. #include <sys/types.h>
  10. int main(int argc, char * argv[]) // ---> ./exe [ip] [port]
  11. {
  12. //1.socket
  13. int fd_client ;
  14. fd_client = socket(AF_INET, SOCK_STREAM, 0);
  15. if(fd_client <= 0)
  16. {
  17. perror("socket");
  18. exit(-1);
  19. }
  20. //2.connect
  21. struct sockaddr_in server_addr ;
  22. memset(&server_addr, 0, sizeof(server_addr));
  23. server_addr.sin_family = AF_INET ;
  24. server_addr.sin_port = htons(atoi(argv[2]));
  25. server_addr.sin_addr.s_addr = inet_addr(argv[1]);
  26. if(-1 == connect(fd_client, (struct sockaddr*)&server_addr, sizeof(server_addr)))
  27. {
  28. perror("connect");
  29. close(fd_client);
  30. exit(-1);
  31. }
  32. //3.send
  33. send(fd_client, "Hello, I am the client !\n", 25, 0);
  34. //4.recv
  35. char buf[128] ="";
  36. int iret = recv(fd_client, buf, 128, 0);
  37. buf[iret] = 0 ;
  38. write(1, buf, strlen(buf));
  39. close(fd_client);
  40. return 0 ;
  41. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注