Linux Socket编程的一些总结

最近写了一些Linux下网络编程的一些程序,做几点总结吧。

先给出客户端后服务器的一些Socket初始化的代码,以后可以直接拿来调用。

客户端Socket初始化代码

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

#include <fcntl.h>

#include <time.h>

#include <strings.h>

#include <sys/types.h>

#include <sys/socket.h>

#include <unistd.h>

#include <arpa/inet.h>

#include <netinet/in.h>

#include <errno.h>

#include <sys/time.h>

#define IP "192.168.1.111"

#define PORT 12346

int init_socket()

{

   struct sockaddr_in server_addr;

   int err;

   int client_socket;

   client_socket=socket(AF_INET,SOCK_STREAM,0);

   if(client_socket<0)

   {

      printf("socket erro\n");

      return ;

   }

   //设置服务器端的地址,端口等

  server_addr.sin_family=AF_INET;

  server_addr.sin_addr.s_addr=inet_addr(IP);//字符串类型转IP类型

  server_addr.sin_port=htons(PORT);

  bzero(&(server_addr.sin_zero),8);

  connect(client_socket,(struct sockaddr *)&server_addr,sizeof(struct sockaddr));//连接服务器

  return client_socket;

}

 

直接调用上面的函数返回一个套接字的文件描述符,利用它便可以和服务器进行通信。

下面给出服务器socket初始化的代码

 

#include <stdio.h>

#include <stdlib.h>

#include <strings.h>

#include <sys/types.h>

#include <sys/socket.h>

#include <unistd.h>

#include <arpa/inet.h>

#include <netinet/in.h>

#include <string.h>

#include <errno.h>

#include <openssl/des.h>

#include <sys/time.h>

#include <fcntl.h>

#define PORT 12346

#define BACKLOG 20

int init_server_socket()

{

   int server_socket,server_client_socket;

   struct sockaddr_in server_addr;



   int err;

   //创建套接字

   server_socket=socket(AF_INET,SOCK_STREAM,0);

   if(server_socket<0)

   {

      printf("socket error\n");

      return -1;

   }

   //设置服务器端的地址,端口等

   server_addr.sin_family = AF_INET;

   server_addr.sin_port = htons(PORT);

   server_addr.sin_addr.s_addr = htons(INADDR_ANY);

   bzero(&(server_addr.sin_zero), 8);

   //将创建的套接字绑定到服务器端

   err = bind(server_socket, (struct sockaddr *)&server_addr, sizeof(struct sockaddr));

   if(err<0)

   {

      printf("bind error\n");

      return -1;

   }

   //监听套接字

   err=listen(server_socket,BACKLOG);

   if(err<0)

   {

      printf("listen error\n");

      return -1;

   }

   return server_socket;

}

上面的初始化函数返回了一个套接字文件描述符,我们在服务器程序中,可以写一个循环,当有客户端连接请求的时候,服务器就建立一个线程和服务器进行通信。代码如下所示:

 

while(1)

    {

        int addrlen=sizeof(struct sockaddr);

        struct sockaddr_in client_addr;

        //如果调用成功,将返回一个新的套接字与客户端通信

        server_client_socket=accept(server_socket,(struct sockaddr*)&client_addr,&addrlen);

        //下面两行是将这个socket连接设置成非阻塞模式

        // int flags = fcntl(server_client_socket, F_GETFL, 0);

        // fcntl(server_client_socket, F_SETFL, flags | O_NONBLOCK);

        printf("%s has connected success\n",inet_ntoa(client_addr.sin_addr));

        //在这里写创建线程程序

        。。。。。。

        usleep(100);

    }

 

要点总结:

 

1、在服务器端程序要判断recv()函数的返回值,如果对方发送的数据比较的则需采用循环接收的方法,比如对方一次发了4096字节的数据,一次rrecv()可能接收不了,则需要多次接收,直到接收的总数等于4096字节,看下面的代码你就会明白

 

#define MAXBUFFER_SIZE 4096

int total_reieved =0;

char recvbuffer[MAXBUFFER_SIZE];

while(1)

       {

          if(MAXBUFFER_SIZE==total_reieved)

              break;

          int size=recv(server_client_socket,recvbuffer+total_reieved,MAXBUFFER_SIZE-total_reieved,0);

          total_reieved+=size;

      }

2、如果发送方的程序关闭了,在接收方就会不断recv()并返回0,则我们就要关闭这个连接,防止接收方陷入死循环

 

3、拔网线拔掉重新插上,socket可以自动恢复连接

4、默认的连接时阻塞模式的,如果要将套接字通信设置成非阻塞模式我们可以参考下面的代码(对套接字文件描述符设置),非阻塞模式下如果读不到数据则返回-1,网络断开也是返回-1

 

int flags = fcntl(server_client_socket, F_GETFL, 0);

fcntl(server_client_socket, F_SETFL, flags | O_NONBLOCK);

 

5、假如客户端程序一直发送数据,服务器程序一直接受数据,这时服务器程序关闭,则客户端程序也会关闭,这时因为服务器close一个连接时,若客户端接这发数据,系统会产生一个SIGPIPE信号,告诉进程连接已经断开了,而处理这个信号的默认动作是使进程退出,如果不想进程退出,可以把SIGPIPE设为SIG_IGN。调用函数signal(SIGPIPE,SIG_IGN);

大概就总结了这几点,欢迎批评和指正。



 

你可能感兴趣的:(socket编程)