linux网络编程--TCP/IP协议

本文介绍了TCP协议在网络传输层的作用及其三次握手建立连接的过程。TCP协议在应用层之上,通过三次握手确保数据同步传输。首先客户端发起连接请求,然后服务器回应并提供下一个数据段的序列号,最后客户端确认服务器的序列号,从而完成连接建立。接下来,简要概述了在Linux环境中实现TCP通信的客户端和服务器程序的基本步骤。
摘要由CSDN通过智能技术生成

特点

  1. TCP协议的位于数据传输层,其上一层是应用层,因此其目的是为了实现一个应用于另一个应用之间数据传输。

  2. TCP协议需要进行三次握手实现数据发送和接收的同步。

    第一次握手:客户端向服务端提出连接请求。这时TCP SYN标 志置位。客户端告诉服务端序列号区域合法,需要检查。客户端 在TCP报头的序列号区中插入自己的ISN。服务端收到该TCP分 段后,。
    第二次握手:接收主机通过发回具有以下项目的数据段表示回 复:同步标志置位、即将发送的数据段的起始字节的顺序号、应 答并带有将收到的下一个数据段的字节顺序号
    第三次握手:客户端确认收到服务端的ISN(ACK标志置位)。到此为止建立完整的TCP连接,开始全双工模式的数据传输过程。

实现过程

1.客户端程序

#include<stdio.h>
#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h> /* superset of previous */
#include <arpa/inet.h>
#include <stdlib.h>
#include <signal.h>
#include <string.h>
#define BUF_SIZE 512
/**********************所用到的函数*******************************
int socket(int domain, int type, int protocol);  
创建套接字函数
AF_INET  IPV4协议   SOCK_STREAM 流套接字
int bind(int sockfd, const struct sockaddr *addr,socklen_t addrlen);
结构体sockaddr的成员
 struct sockaddr {
           sa_family_t sa_family;
           char        sa_data[14];
 }
struct sockaddr_in {
           sa_family_t    sin_family; /* address family: AF_INET 
           in_port_t      sin_port;   /* port in network byte order
           struct in_addr sin_addr;   /* internet address 
       };
struct in_addr {
           uint32_t       s_addr;     /* address in network byte order 
       };

   int listen(int sockfd, int backlog);
   sighandler_t signal(int signum, sighandler_t handler);
   int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
   int connect(int sockfd, const struct sockaddr *addr,socklen_t addrlen);
   char *fgets(char *s, int size, FILE *stream);//接收终端输入文件流
    ********************************************************/
int main()
{
int client_id;
struct sockaddr_in clientadd;
char buffer[BUF_SIZE];
client_id=socket(AF_INET,SOCK_STREAM,0);  //创建套接字
clientadd.sin_family=AF_INET;   //结构体成员赋值
clientadd.sin_port=htons(9736);//指定端口号
clientadd.sin_addr.s_addr=inet_addr("192.168.1.121"); //绑定IP地址,此处的IP为服务器IP
if(connect(client_id,(struct sockaddr *)&clientadd,sizeof(clientadd))==-1)//创建连接
{
    //链接失败
    printf("connect   failed!\n");
    exit(EXIT_FAILURE);
}
printf("please input:");
fgets(buffer,BUF_SIZE,stdin);
//向服务器写
write(client_id,buffer,BUF_SIZE);//将获取的数据发送至缓冲区
sleep(rand()%3);
memset(buffer,0,strlen(buffer));
read(client_id,buffer,BUF_SIZE);//接收返回数据
printf("You input:%s\n",buffer);
close(client_id);
return 0;
}

2.服务器程序

服务器程序主要实现从客户端接收数据,将接收到的数据返回给客户端。

#include<stdio.h>
#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h> /* superset of previous */
#include <arpa/inet.h>
#include <stdlib.h>
#include <signal.h>
#include <string.h>
#define BUF_SIZE 512
/********用到的函数************************
int socket(int domain, int type, int protocol);  创建套接字
AF_INET  IPV4协议   SOCK_STREAM
int bind(int sockfd, const struct sockaddr *addr,socklen_t addrlen);
   struct sockaddr {
           sa_family_t sa_family;
           char        sa_data[14];
       }
   struct sockaddr_in {
           sa_family_t    sin_family; /* address family: AF_INET 
           in_port_t      sin_port;   /* port in network byte order
           struct in_addr sin_addr;   /* internet address 
       };
   struct in_addr {
           uint32_t       s_addr;     /* address in network byte order 
       };
   int listen(int sockfd, int backlog);
   sighandler_t signal(int signum, sighandler_t handler);

   int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
    ********************************************************/

int main()
{

int socket_id,client_id;
struct sockaddr_in serveradd;
struct sockaddr_in clientadd;
int clientlen;
char buffer[BUF_SIZE+1];
socket_id=socket(AF_INET,SOCK_STREAM,0);  //创建套接字
serveradd.sin_family=AF_INET;
serveradd.sin_port=htons(9736);//指定端口好
serveradd.sin_addr.s_addr=htonl(INADDR_ANY); //绑定IP地址    这里指定监听的IP地址是任何一个访问的IP
if(bind(socket_id,(struct sockaddr *)&serveradd,sizeof(serveradd))==-1)
{
    //绑定失败
    printf("connect   failed!\n");
    exit(EXIT_FAILURE);
}
//服务器端需要绑定端口和IP,服务器端需要对固定的端口和指定的IP进行监听,因此需要进行bind操作,而客户端部分不需要
listen(socket_id,5);//最大允许5个客户端访问
signal(SIGCHLD,SIG_IGN);
while(1)
{
    clientlen=sizeof(clientadd);
    printf("please waiting....\n");
    client_id=accept(socket_id,(struct sockaddr *)&clientadd,&clientlen);//监听zijincheng
    if(fork()==0)//新建一个子进程,在子进程中实现接收客户端发送过来的内容并将其发送回去,同时显示在终端上。
    {
        read(client_id,buffer,BUF_SIZE);
        buffer[BUF_SIZE]='\0';
        printf("You input :%s\n",buffer);
        sleep(rand()%3);
        write(client_id,buffer,BUF_SIZE);
        close(client_id);
        exit(EXIT_SUCCESS);
    }
    else
    {
        close(client_id);//关闭子进程
    }
}
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值