网络IPC, socket(3): 建立连接

来源:互联网 发布:apm软件下载 编辑:程序博客网 时间:2024/05/18 01:47

1. 前提:

    如果处理的是面向连接的网络服务(SOCK_STREAM或SOCK_SEQPACKET), 在开始传输数据之前, 需要在客户端和服务器端建立一个连接.

 

2. 函数介绍:

用connect建立一个连接:

  • 头文件: <sys/socket.h>
  • 原型: int connect(int sockfd, const struct sockaddr *addr, socklen_t len);
  • 返回值: 成功则返回0, 出错则返回-1.
  • 说明: 在connect中所指定的地址是想与之通信的服务器地址.

 

用listen进行监听(可以接受连接请求):

  • 头文件: <sys/socket.h>
  • 原型: int listen(int sockfd, int backlog);
  • 返回值: 成功则返回0, 出错则返回-1.
  • 参数: backlog提供了一个提示, 用于表示该进程可以入队等待的连接请求数量. 其实际上限值由系统和协议决定. 一旦队列满, 系统会拒绝多余的连接请求, 所以该值应该基于服务器期望负载量和处理能力来选择.

 

服务器调用了listen以后, socket就可以接收连接请求了.

用accept获得连接请求并建立连接:

  • 头文件: <sys/socket.h>
  • 原型: int accept(int sockfd, struct sockaddr *restrict addr, socklen_t *restrict len);
  • 返回值: 成功则返回socket描述符, 出错则返回-1.
  • 参数: 如果不关心客户端标识, 可以将addr和len设为NULL; 否则, 在调用accept之前, 应确保参数addr的缓冲区有足够大的空间来存放地址, 并且将len设为对应大小.

    这个返回的socket与原始的socket(sockfd参数)具有相同的socket类型和地址族, 但并没有关联. 原始socket继续保持可用状态并接受其他连接请求.

    如果没有连接请求, accept会阻塞; 如果sockfd处于非阻塞模式, accept会返回-1并将errno设置为EAGAIN或EWOULDBLOCK.

    另外, 服务器可以使用poll或select来等待一个请求到来, 在以后的文章中将介绍.

 

3. 举例:

客户端的连接程序:

#include<sys/types.h>
#include
<sys/socket.h>
#include
<netinet/in.h>
#include
<arpa/inet.h>
#define PORT 1234
#define SERVER_IP “127.0.0.1”

int main()
{
    
int s;
    
struct sockaddr_in addr;
    
char buffer[256];
    
if((s = socket(AF_INET,SOCK_STREAM,0))<0){
        perror(“socket”);
        exit(
1);
    }


    
/* 填写sockaddr_in结构*/
    bzero(
&addr,sizeof(addr));
    addr.sin_family 
= AF_INET;
    addr.sin_port
=htons(PORT);
    addr.sin_addr.s_addr 
= inet_addr(SERVER_IP);

    
/* 尝试连线*/
    
if(connect(s,&addr,sizeof(addr))<0){
        perror(“connect”);
        exit(
1);
    }

    
return 0;
}

 

服务器端的监听程序:

#include<sys/socket.h>
#include
<netinet/in.h>
#include
<arpa/inet.h>
#define PORT 1234
#define MAXSOCKFD 10

int main()
{
    
int sockfd, newsockfd;
    
struct sockaddr_in addr;
    
int addr_len = sizeof(struct sockaddr_in);
    
    
/* 创建socket */
    
if ((sockfd = socket(AF_INET,SOCK_STREAM,0))<0){
        perror(“socket”);
        exit(
1);
    }


    
/* 填充addr */
    bzero(
&addr,sizeof(addr));
    addr.sin_family 
=AF_INET;
    addr.sin_port 
= htons(PORT);
    addr.sin_addr.s_addr 
= htonl(INADDR_ANY);

    
/* 绑定 */
    
if(bind(sockfd,&addr,sizeof(addr))<0){
        perror(“connect”);
        exit(
1);
    }


    
/* 监听 */
    
if(listen(sockfd,3)<0){
        perror(“listen”);
        exit(
1);
    }


    
/* 接受请求 */
    
if((newsockfd = accept(sockfd, NULL, NULL)) < 0){
        perror(
"accept");
        exit(
1);
    }


    
return 0;
}