Linux 网络编程——TCP

一、TCP通信步骤

TCP服务器部分:

1、调用函数socket(),创建一个socket

2、设置sockaddr_in信息,如要连接服务器的IP和端口等属性

3、调用函数bind(),绑定IP地址、端口等信息到socket上

4、调用函数listen(),设置允许的最大连接数

5、调用函数accept(),等待来自客户端的连接请求

6、调用函数send() 和 recv() 或者 read() 和 write() ,收发数据

7、调用close(),关闭网络连接

TCP客户端部分:

1、调用函数socket(),创建一个socket

2、设置sockaddr_in信息,如要连接服务器的IP和端口等属性

3、调用函数connect(),连接服务器

4、调用函数send() 和 recv() 或者 read() 和 write() ,收发数据

5、调用close(),关闭网络连接

 

从整体上看:

 

服务端: 

1、创建socket

   int socket(int domain,int type,int protocol)

 

参数domain 指定使用何种的地址类型:

PF_INET / AF_INET Ipv4网络协议;

PF_UNIX / PF_LOCAL / AF_UNIX / AF_LOCAL UNIX 进程通信协议

 

type为传输类型:

 

SOCK_STREAM 提供双向连续且可信赖的数据流,即TCP。

SOCK_DGRAM 使用不连续不可信赖的数据包连接,即UDP。

protocol用来指定socket所使用的传输协议编号,通常设为0即可。

 

成功则返回新的socket处理代码,失败返回-1。

 

 

2、sockaddr_in 结构体信息填充

 

  1. struct sockaddr_in  
  2. {  
  3.        short int sin_family;     //网络协议类型      
  4.         unsigned short int sin_port;     //端口号  
  5.         struct in_addr sin_addr;         //目的地址结构体,其中有s_addr要做设定  
  6.         unsigned char sin_zero[8];       //无用字节为0即可,不用设置  
  7. }  

 

 

0、将结构体初始化

        void bzero(void *s,int n)


      头文件为<string.h>。bzero()会将参数s所指的内存区域前n个字节,全部设为零值。相当于调用memset((void*)s,0,size_tn);

 

1、sin_family:

     协议类型与socket的domain相同。如:PF_INET

2、sin_port:

        unsigned short int htons(unsigned short int hostshort);

     htons()用来将参数指定的16位hostshort转换成网络字符顺序。返回对应的网络字符顺序。

3、sin_addr:设置的是sin_addr.s_addr

        unsigned long int inet_addr(const char *cp);

         inet_addr()用来将参数cp所指的网络地址字符串转换成网络所使用的二进制数字。网络地址字符串是以数字和点组成的字符串,例如:“127.0.0.1”。成功则返回对应的网络二进制的数字,失败返回-1。

        unsigned long int htonl(unsigned long int hostlong);

       htonl()用来将参数指定的32位hostlong 转换成网络字符顺序。返回对应的网络字符顺序。通常为INADDR_ANY。

        INADDR_ANY就是指定地址为0.0.0.0的地址,表示所有地址。 一般来说,在各个系统中均定义成为0值。

3、bind信息到socket

           int bind(int sockfd,struct sockaddr * my_addr,int addrlen);

 

    sockfd为socket函数的返回值。

    my_addr 为刚才填写的结构体,要类型转换 (SA *)&myadd。

    addrlen为结构体的大小,用sizeof函数算。

   

   成功返回0,失败返回-1。

4、listen设置连接数

             int listen(int sockfd,int backlog);
 
      listen()用来设定ssockfd的最大连接数(backlog),如果连接数目达此上限则client端将收到ECONNREFUSED的错误。Listen()并未开始接收连线,只是设置socket为listen模式,真正接收client端连线的是accept()。成功则返回0,失败返回-1。

 

5、accept等待连接请求

            int accept(int socketfd,struct sockaddr * addr,int * addrlen);
 
           accept()用来接受参数socketfd连线。当有连线进来时accept()会返回一个新的socket处理代码,往后的数据传送与读取就是经由新的socket处理,而原来参数socketfd能继续使用accept()来接受新的连线要求。

     

    连线成功时,参数addr所指的结构会被系统填入远程主机的地址数据。

 

      addrlen为scokaddr的结构长度的指针

    成功则返回新的socket处理代码,相当于文件操作符,失败返回-1。

客户端:

3、connect连接

          int connect (int sockfd,struct sockaddr * serv_addr,int addrlen);

        用来将参数sockfd的socket连至参数serv_addr指定的网络地址。参数addrlen为sockaddr的结构长度。
      成功则返回0,失败返回-1

二、举例

  1. //server  
  2. #include<stdio.h>  
  3. #include<sys/socket.h>  
  4. #include<sys/types.h>  
  5. #include<unistd.h>  
  6. #include<stdlib.h>  
  7. #include<netinet/in.h>  
  8. #include<arpa/inet.h>  
  9. #include<memory.h>  
  10. int main(int argc,char *argv[]){  
  11.   
  12.         struct sockaddr_in sev_addr,new_addr;  
  13.         int sockfd,new_fd=0;  
  14.         char buff[1024];  
  15.         int nbytes;  
  16.         int struct_size;  
  17.         if(argc != 2){  
  18.                 printf("Usage : %s <hostname>\n",argv[0]);  
  19.                 return 1;  
  20.         }  
  21.   
  22.         if((sockfd=socket(PF_INET,SOCK_STREAM,0))<0){  
  23.                 printf("socket create error!\n");  
  24.                 return 1;  
  25.         }  
  26.         bzero(&sev_addr,sizeof(struct sockaddr_in));  
  27.         sev_addr.sin_family = PF_INET;  
  28.         sev_addr.sin_port = htons(8888);  
  29.         sev_addr.sin_addr.s_addr = inet_addr(argv[1]);  
  30.   
  31.         if(bind(sockfd,(struct sockaddr*)&sev_addr,sizeof(struct sockaddr_in))<0){  
  32.                 printf("bind error!\n");  
  33.                 return 1;  
  34.         }  
  35.         if(listen(sockfd,5)<0){  
  36.                 printf("Listen set error!\n");  
  37.                 return 1;  
  38.         }  
  39.         while(1){  
  40.                 struct_size=sizeof(struct sockaddr_in);  
  41.                 bzero(&new_addr,sizeof(struct sockaddr_in));  
  42.                 if(new_fd=accept(sockfd,(struct sockaddr*)&new_addr,&struct_size)<0){  
  43.                         printf("accept error!\n");  
  44.                         return 1;  
  45.                 }  
  46.                 printf("The %s is conneted!\n",inet_ntoa(new_addr.sin_addr));  
  47.                 memset(buff,'\0',sizeof(buff));  
  48.                 if((nbytes=read(new_fd,buff,1024)) == -1){   //第一次读是从服务端输入流读入的不知是什么原因?求解释  
  49.                         printf("read error\n");  
  50.                         return 1;  
  51.                 }  
  52.                 printf("read over the nbytes is %d\n",nbytes);  
  53.                 buff[nbytes]='\0';  
  54.                 printf("Server receive the message: %s",buff);  
  55.                 close(new_fd);  
  56.                 printf("exit.....\n");  
  57.         }  
  58.   
  59.   
  60. }  
 
  1. //client  
  2. #include<stdio.h>  
  3. #include<sys/socket.h>  
  4. #include<sys/types.h>  
  5. #include<unistd.h>  
  6. #include<stdlib.h>  
  7. #include<netinet/in.h>  
  8. #include<arpa/inet.h>  
  9. #include<memory.h>  
  10. int main(int argc,char *argv[]){  
  11.   
  12.         struct sockaddr_in clin_addr,new_addr;  
  13.         int sockfd,new_fd;  
  14.         char buff[1024];  
  15.         int nbytes;  
  16.         int struct_size;  
  17.         if(argc != 2){  
  18.                 printf("Usage : %s <hostname>\n",argv[0]);  
  19.                 return 1;  
  20.         }  
  21.   
  22.         if((sockfd=socket(PF_INET,SOCK_STREAM,0))<0){  
  23.                 printf("socket create error!\n");  
  24.                 return 1;  
  25.         }  
  26.         bzero(&clin_addr,sizeof(struct sockaddr_in));  
  27.         clin_addr.sin_family = PF_INET;  
  28.         clin_addr.sin_port = htons(8888);  
  29.         clin_addr.sin_addr.s_addr = inet_addr(argv[1]);  
  30.         if(connect(sockfd,(struct sockaddr*)&clin_addr,sizeof(struct sockaddr_in))<0){  
  31.                 printf("connect error!\n");  
  32.                 return 1;    
  33.         }  
  34.         memset(buff,'\0',1024);  
  35.         fgets(buff,1024,stdin);  
  36.         write(sockfd,buff,strlen(buff));  
  37.         close(sockfd);  
  38.         printf("client will exit!\n");  
  39.         return 0;  
  40. }  


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值