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

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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值