Linux下Socket TCP编程

一、新手入门

1、socket即为套接字,在TCP/IP协议中,“IP地址+TCP或UDP端口号”唯一的标识网络通讯中的一个进程,“IP地址+TCP或UDP端口号”就为socket。


2、在TCP协议中,建立连接的两个进程(客户端和服务器)各自有一个socket来标识,则这两个socket组成的socket pair就唯一标识一个连接。


3、socket本身就有“插座”的意思,因此用来形容网络连接的一对一关系,为TCP/IP协议设计的应用层编程接口称为socket API。

很简单,全部注释了!

二、基本步骤:

1)创建客户端的socket(初始化)。

2)向服务器发起连接请求。

3)与服务端通信,发送一个报文后等待回复,然后再发下一个报文。

4)不断的重复第3)步,直到全部的数据被发送完。

5)第4步:关闭socket,释放资源。

三、代码部分

server.cpp

/*Socket 客户端(server)编程
1)创建客户端的socket(初始化)。

2)向服务器发起连接请求。

3)与服务端通信,发送一个报文后等待回复,然后再发下一个报文。

4)不断的重复第3)步,直到全部的数据被发送完。

5)第4步:关闭socket,释放资源。
*/
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<errno.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<netinet/ip.h>
#include<unistd.h>
#include<arpa/inet.h>
#include <sys/time.h>    
#include <unistd.h>

#define MAXLINE 25

int main(int argc, char** argv)
{
    int  listenfd, connfd;
    struct sockaddr_in  servaddr;
    char  buff[25];
    int  n,cnt=0,i;//定义变量
    int res,ret;
    
    //char buf111[8] = {char(0x01),char(0x03),char(0x00),char(0x65),char(0x00),char(0x06),char(0xD5),char(0xD7)};
        struct  timeval    tv1,tv2;    //时间函数,没有用到!
    //AF_INET(又称 PF_INET)是 IPv4 网络协议的套接字类型,AF_INET6 则是 IPv6 的;而 AF_UNIX 则是 Unix 系统本地通信。
    //SOCK_STREAM提供面向连接的稳定数据传输,即TCP协议。
    if( (listenfd = socket(AF_INET, SOCK_STREAM, 0)) == -1 ){//创建socket,parameters:地址类型、套接字类型、协议(此处默认TCP)
        printf("create socket error: %s(errno: %d)\n",strerror(errno),errno);
        return 0;
    }


//extern void *memset(void *buffer, int c, int count) 把buffer所指内存区域的前count个字节设置成c的值。
    memset(&servaddr, 0, sizeof(servaddr));//给指定内存初始化,parameters:内存首地址,初始化值,内存大小
    servaddr.sin_family = AF_INET;//地址家族
    servaddr.sin_addr.s_addr =htonl(INADDR_ANY);//htonl就是把本机字节顺序转化为网络字节顺序;INADDR_ANY:任何地址,即client绑定任何一个主机地址都可以建立连接
    servaddr.sin_port = htons(8888);//端口号;htons() 是网络字节序与主机字节序之间转换的函数。

//bind服务端把用于通信的地址和端口绑定到socket上
    if( bind(listenfd, (struct sockaddr*)&servaddr, sizeof(servaddr)) == -1){//绑定地址和端口,parameters:socket,指向sockaddr_in结构体变量的指针,结构体变量所占内存的大小
        printf("bind socket error: %s(errno: %d)\n",strerror(errno),errno);
        return 0;
    }

    if( listen(listenfd, 10) == -1){//监听套接字
        printf("listen socket error: %s(errno: %d)\n",strerror(errno),errno);
        return 0;
    }
        //通过程序获取刚建立连接的socket的客户端的IP地址和端口号
        struct sockaddr_in cin;
        socklen_t addrlen = sizeof(cin);//此处socklen_t为sys/socket.h文件提供,相当于unsigned int类型

        if((connfd = accept(listenfd,(struct sockaddr *)&cin,&addrlen)) < 0)//接受连接,parameters:监听套接字,指向sockaddr_in结构体变量的指针(存储刚建立连接的socket的客户端的IP地址和端口号),地址(存储客户端结构体长度)
        {
            printf("accept err\n");
            exit(1);
        }

        char ipv4_addr[16];
        if(!inet_ntop(AF_INET,(void *)&cin.sin_addr,ipv4_addr,sizeof(cin)))//将数值格式转化为点分十进制的ip地址格式,parameters:地址家族,指向数值格式地址指针,点分十进制的ip地址格式指针,目标存储单元大小
        {
            printf("inet_ntop\n");
            exit(1);
        }
        printf("Client(%s:%d) is connected!\n",ipv4_addr,htons(cin.sin_port));
        
    printf("======waiting for client's request======\n");
    while(1){
          cnt++;
                printf("%drecv msg from client:",cnt);
                memset(buff, 0, sizeof(buff));
                n = recv(connfd, buff, MAXLINE, 0);//不论是客户还是服务器应用程序都用recv函数从TCP连接的另一端接收数据。parameters:套接字,指向存储数据单元的指针,存储单元的大小,flags 标志
                if(n > 0)
                    {                
                        for(i = 0;i< n;i++)
                       printf("%c ", buff[i]);              
                    }
             
            printf("\n"); 
            
            send(connfd, buff, n,MSG_NOSIGNAL);  //将接收到的数据发送回去,parameters:套接字,指向存储数据单元的指针,存储单元的大小,flags 标志(MSG_NOSIGNAL 禁止向系统发送异常信息)
                     
        
    }
    close(connfd);
    close(listenfd);
    return 0;
}

client.cpp

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<errno.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<unistd.h>

#define MAXLINE 25

int main(int argc, char** argv){
    int   sockfd, n,i,cnt=0;
    char  recvline[25], sendline[25];
    struct sockaddr_in  servaddr;
        char buf111[8] = {char(0x01),char(0x03),char(0x00),char(0x65),char(0x00),char(0x06),char(0xD5),char(0xD7)};
        char  buff[25];
        
    //创建套接字
    if( (sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0){
        printf("create socket error: %s(errno: %d)\n", strerror(errno),errno);
        return 0;
    }
    //填写sockaddr_in结构体
    memset(&servaddr, 0, sizeof(servaddr));
    servaddr.sin_family = AF_INET;
   // servaddr.sin_addr.s_addr=inet_addr("192.168.60.135");
    servaddr.sin_port = htons(8888);
    // if( inet_pton(AF_INET, argv[1], &servaddr.sin_addr) <= 0){
	// printf("inet_pton error for %s\n",argv[1]);
    //     return 0;
    // }
    //发送连接请求
    if( connect(sockfd, (struct sockaddr*)&servaddr, sizeof(servaddr)) < 0){
        printf("connect error: %s(errno: %d)\n",strerror(errno),errno);
        return 0;
    }
    //发送数据、接受数据
    while(1)
    {
         sleep(1);
         cnt++; 
        for(int i=0;i<8;i++)
        {
            scanf("%c",&buf111[i]);
        }              
         send(sockfd, buf111, sizeof(buf111),MSG_NOSIGNAL);
         printf("%dsend ok\n",cnt);
         printf("%drecv msg from client:",cnt);
         memset(buff, 0, sizeof(buff));
         n = recv(sockfd, buff, MAXLINE, 0);
         if(n > 0)
         {                
             for(i = 0;i< n;i++)
               printf("%02X ", buff[i]);              
         }
             
           printf("\n"); 
                     
      }
    close(sockfd);
    return 0;
}

server.cpp与client.cpp同时启动

client中输入地址!

如下:

  • 0
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值