linux下实现简单socket通讯

本文在gnu/linux环境编程一书的基础上进行补充和扩展。

先看server端的代码部分:

int main ( void )
{
  int serverFd, connectionFd;
  struct sockaddr_in servaddr;
  char timebuffer[MAX_BUFFER+1];
  time_t currentTime;
  serverFd = socket( AF_INET, SOCK_STREAM, 0 );
  memset( &servaddr, 0, sizeof(servaddr) );
  servaddr.sin_family = AF_INET;
  servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
  servaddr.sin_port = htons(DAYTIME_SERVER_PORT);
  bind( serverFd, 
         (struct sockaddr *)&servaddr, sizeof(servaddr) );
  listen( serverFd, 5 );
  while ( 1 ) {
    connectionFd = accept( serverFd, 
                          (struct sockaddr *)NULL, NULL );
    if (connectionFd >= 0) {
      currentTime = time(NULL);
      snprintf( timebuffer, MAX_BUFFER, 
                "%s\n", ctime(&currentTime) );
      write( connectionFd, timebuffer, strlen(timebuffer) );
      close( connectionFd );
    }
  }
}

宏 DAYTIME_SERVER_PORT  为  13,此为知名端口,需在执行server时添加sudo。

第一步:创建socket(相当于在协议栈内部开辟一块内存空间,用于存放控制信息)

  网络地址族 AF_INET,表明要使用ipv4网络协议。 AF全称为address framily地址族,貌似和PF(也就是protocol family协议族)差不多。参考https://www.jianshu.com/p/3b10c4ec6d8e

  第二个参数定义通信的语法,SOCK_STREAM类型对应流类型的通信(TCP),这个最常用。

第二步:绑定

  初始化需要绑定的socket控制信息(地址族+IP地址+端口)

  INADDR_ANY代表允许接收所有地址的请求消息,也可用inet_addr("x.x.x.x")来指定服务器某个网卡的ip,在ch13_socket_amend/文件夹中有指定服务器的地址为127.0.0.110,你也可以自个替换,不过得确保和客户端请求的地址一致。

  htonl函数将一个32位地址数从主机字节顺序转换成网络字节顺序。(host to net long int)

  htons函数将一个16位数从主机字节顺序转换成网络字节顺序。参考https://blog.csdn.net/haoxiaodao/article/details/73162663

扫描二维码关注公众号,回复: 8944867 查看本文章

第三步:监听

第四步:调用accept进入阻塞,等待客户端连接,连接后获取客户端的ip及port。

客户端部分代码:

  connectionFd = socket(AF_INET, SOCK_STREAM, 0);
  
  memset(&cliaddr, 0, sizeof(cliaddr));
  cliaddr.sin_family = AF_INET;
  cliaddr.sin_port = htons(DAYTIME_CLIENT_PORT);
  cliaddr.sin_addr.s_addr = inet_addr("127.0.0.123");//client ip

  memset(&servaddr, 0, sizeof(servaddr));
  servaddr.sin_family = AF_INET;
  servaddr.sin_port = htons(DAYTIME_SERVER_PORT);
  servaddr.sin_addr.s_addr = inet_addr("127.0.0.110");//server ip
  
  bind(connectionFd,(struct sockaddr *)&cliaddr, sizeof(cliaddr) );
  
  connectValue=connect(connectionFd,(struct sockaddr *)&servaddr, sizeof(servaddr));
  printf("connect %d\n",connectValue);
  if(connectValue==0)//check if connectted.
  {
    int ret=0,size;
    size = sizeof(tmpaddr);
  	ret=getsockname(connectionFd,(struct sockaddr *)&tmpaddr,&size );
  	if(ret>=0){
      printf("client ip:%s, port:%d\n",inet_ntoa(tmpaddr.sin_addr),ntohs(tmpaddr.sin_port));
    }
  }
  while ( (in = read(connectionFd, &timebuffer[index], limit)) > 0) {
    index += in;
    limit -= in;
  }
  timebuffer[index] = 0;
  printf("\n%s\n", timebuffer);

调用connect()函数时进程会进入阻塞态,向服务端发送请求,通过三次握手来建立TCP连接。

connect()函数在第二次握手时会有返回值,accept()在第三次时有返回值。

getsockname() 函数能够获取指定套接口描述符的控制信息,需要在connect连接成功后获取。客户端如果没用bind绑定指定ip和端口,系统会自动分配,服务器如果使用INADDR_ANY做为绑定的ip地址,则获取到的ip值为0.0.0.0

  用ch13_socket_amend 文件夹里的代码编译运行后的log:

持续更新ing

参考文章:https://www.cnblogs.com/cy568searchx/p/4211124.html

发布了23 篇原创文章 · 获赞 16 · 访问量 5659

猜你喜欢

转载自blog.csdn.net/xiong3110/article/details/85223847
今日推荐