linux网络编程(二)——TCP编程

如前面那篇博客:linux网络编程(一)(点击打开链接)所讲,TCP编程模型如下图所示

linux网络编程(二)——TCP编程_第1张图片

1、具体用到的函数如下:

服务器端:

创建socket: socket()   绑定地址:bind()    监听端口:listen()  等待链接:accept()  /收数据:send()/recv()  结束连接:close()

客户机端:

创建socket: socket() 连接服务器:connect()  /收数据:send()/recv()  结束连接:close()

2、涉及函数详解——可参考《UNIX环境高级编程》第16章,里面讲的很详细。


2.1创建套接字   socket函数

套接字是通信端点的抽象。类似于应用程序使用文件描述符访问文件,访问套接字必须通过套接字描述符。其实,套接字描述符是用文件描述符实现的,它也是int类型的一个量。创建套接字可以调用socket函数。

  1. int socket(int domain, int type, int protocol);//成功返回套接字描述符.出错返回-1

  2. 形参domain: 域,确定通信的特性,包括地址格式。表示各个域的常数通常以AF_开头,意指地址族(address family)。比如AF_INET表示IPV4英特网域,AF_INET6表示IPV6英特网域。

  3. 形参type:确定套接字类型,进一步确定通信特征。取值参考下图:
  4. linux网络编程(二)——TCP编程_第2张图片
参数protocal:该参宿通常是0,按给定的域和套接字类型选择默认协议。仅当同一域和套接字类型支持多个协议时,可用protocal选择一个特定协议。在AF_INET域中,套接字类型SOCK_STREAM默认协议时TCP(传输控制协议),套接字类型SOCK_DGRAM默认协议是UDP(用户数据报协议)。对于SOCK_STREAM和SOCK_DGRAM的详细区别,可以参考《UNIX环境高级编程》第16章。
2.2绑定地址   bind函数
  1. 这里说的绑定是将套接字与地址绑定。客户端上的套接字不需要我们去绑定地址,系统会选一个默认地址。而对于服务器,需要给一个接受客户端请求的套接字绑定一个众所周知的地址。bind函数可以将套接字与地址绑定。如下图
  2. linux网络编程(二)——TCP编程_第3张图片
  3. 对于因特网域,如果指定的IP为INADDR——ANY,套接字端点可以绑定到所有的系统网络接口,这意味着可以收到这个系统所安装的所有网卡的数据包。
关于地址格式问题,请看文章:linux网络编程基础知识——网络地址格式和网络字节序
  1. 2.3设置监听   listen函数
  2. linux网络编程(二)——TCP编程_第4张图片
  3. 服务器调用listen之后,表示它可以接受连接请求了,后面服务器变开始接受客户端发来的连接请求,并建立连接。
  4. 2.4等待连接   accept函数
  5. linux网络编程(二)——TCP编程_第5张图片
  6. addr和len的作用不是把信息传给accept,而是把accept的信息传出来。accept会将与服务器通信的客户端的地址存放到addr内,将地址的长度存放在len内。如果没有连接请求等待处理,即如果没有客户端请求与服务器建立连接,accept会阻塞知道一个请求的到来。
  7. 连接建立之后,accept返回的文件描述符就是套接字描述符,即代表一个新的套接字,新套接字连接到相应的客户端。这个新的套接字描述符和原来的套接字sockfd具有相同的套接字类型和地址族。

  8. 2.5发送数据   send函数
  9. linux网络编程(二)——TCP编程_第6张图片
  10. 2.6接收数据   recv函数
  11. linux网络编程(二)——TCP编程_第7张图片
  12. 2.7关闭连接  close函数
  13. 用法和文件操作的close函数相同。直接close(sockfd).
  14. 2.8连接服务器  connect函数
  15. linux网络编程(二)——TCP编程_第8张图片
  16. 3、实例(这些代码都是跟着国嵌的视频课程编写的,都是比较简单的功能)
  17. 编写一个TCP服务器程序和客户端程序,实现功能是:在客户端通过键盘输入一些字符,这些字符会发送到服务器,并在服务器上打印出来。

  18. 服务器段程序:
  19. #include
    #include
    #include
    #include
    #include
    #include
    
    
    #define portnum 3333 //随便定义一个端口
    
    
    int main()
    {
    int sockfd, new_fd;
    struct sockaddr_in server_addr;//服务器地址
    struct sockaddr_in clint_addr; //客户机地址
    char buffer[128];
    int nbite;
    int sin_size;
    
    //1. 创建套接字
    if((sockfd=socket( AF_INET, SOCK_STREAM, 0)) == -1)//如果创建套接字失败
    {
    printf("create socket error!\n");
    exit(1); 
    }
    
    //2.1 设置要绑定的地址,对server_addr初始化
    bzero(&server_addr,sizeof(struct sockaddr_in));//全部成员清0
    
    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons( portnum);//转换成网络字节序
    server_addr.sin_addr.s_addr = htonl( INADDR_ANY);//转换成网络字节序
    
    //2.2 绑定地址
    bind( sockfd, (struct sockaddr *)&server_addr, sizeof(struct sockaddr) );
    
    //3. 监听端口
    listen(sockfd, 5);
    
    while(1)
    {
    //4. 等待连接
    sin_size = sizeof(struct sockaddr);
    new_fd = accept(sockfd,(struct sockaddr *)(&clint_addr),&sin_size);
    
    printf("server get connection from %s\n",(inet_ntoa(clint_addr.sin_addr)) );//打印出连接服务器的客户机地址
    //5. 接收数据
    nbite = recv( new_fd, buffer, 128, 0);//返回接收到的数据长度
    buffer[nbite] = '\0';
    printf("server received: %s\n",buffer ); 
    
    //6. 结束连接
    close( new_fd );
    }
    
    close(sockfd);
    
    return 0; 
    }
    


客户端程序:
#include
#include
#include
#include
#include
#include


#define portnum 3333 //要与之建立连接的服务器端口号


int main()
{
struct sockaddr_in server_addr;
int sockfd, new_fd;
char buffer[128];

//1. 创建套接字
if((sockfd=socket( AF_INET, SOCK_STREAM, 0)) == -1)//如果创建套接字失败
{
printf("create socket error!\n");
exit(1); 
}

//2.1 设置连接的服务器的地址
bzero(&server_addr,sizeof(struct sockaddr_in));//全部成员清0

server_addr.sin_family = AF_INET;
server_addr.sin_port = htons( portnum);//转换成网络字节序
server_addr.sin_addr.s_addr =  inet_addr("10.2.10.26");//将服务器地址写死,设置成虚拟机地址。inrt_addr转换得到的是网络字节序地址

//2.2 连接服务器
if(connect(sockfd,(struct sockaddr *)(&server_addr),sizeof(struct sockaddr)) == -1)
{
printf("connect error!\n");
exit(1); 
}

//3. 发送数据到服务器
printf("please input char:\n");
fgets(buffer, 128, stdin); //从标准输入拿到字符,存入buff
send(sockfd, buffer,strlen(buffer), 0);

//4 关闭连接
close(sockfd);

return 0; 
}



参考资料:《UNIX环境高级编程》
  1. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

  2. 转载请注明出处:
  3. CSDN作者:Andoubi
  4. 原文链接:http://blog.csdn.net/andoubi/article/details/51778988

你可能感兴趣的:(linux网络编程)