linux TCP socket 通信

linux TCP socket 通信

刚学完socket编程 稍微总结下吧

再写代码之前 应该先对tcp三次握手协议有所了解

引用高人的话 简单介绍下

在TCP/IP协议中,TCP协议提供可靠的连接服务,采用三次握手建立一个连接。

第一次握手:建立连接时,客户端发送syn包(syn=x)到服务器,并进入SYN_SEND状态,等待服务器确认;
第二次握手:服务器收到syn包,必须确认客户的SYN(ack=x+1),同时自己也发送一个SYN包(syn=y),即SYN+ACK包,此时服务器进入SYN_RECV状态;
第三次握手:客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ack=y+1),此包发送完毕,客户端和服务器进入ESTABLISHED状态,完成三次握手。

结合图来看下吧

 

有了以上基础 先看一个简单TCP通信程序

 客户端在终端输入字符,发送至服务器端,在服务器端将小写变成大写然后返回客户端

服务器端

#include<string.h>

#include<strings.h>

#include<sys/types.h>

#include<sys/socket.h>

#include<netinet/in.h>

#include<arpa/inet.h>

 

#define SERV_TCP_PORT 6601

#define EXIT_FAILURE 1

 

int main()

{

  int sockfd,len,s,n,i;

  struct sockaddr_in sa,ca;

  char buf[512];

  

  sockfd = socket(AF_INET,SOCK_STREAM,0);

  

  sa.sin_family = AF_INET;

  sa.sin_addr.s_addr = htonl(INADDR_ANY);

  sa.sin_port = htons(SERV_TCP_PORT);

 

  n = bind(sockfd, (struct sockaddr *) &sa, sizeof(sa)); 

  if(n == -1){

    perror("bind");  exit(EXIT_FAILURE);

  } 

  listen(sockfd,5);

  len = sizeof(ca);

  s = accept(sockfd, (struct sockaddr *) &ca, (socklen_t *) &len);

  printf("Connected\n");

 

  for(;;){

    n = recv(s,buf,sizeof(buf),0);

    buf[n] = 0;

    fputs(buf,stdout);  

    fflush(stdout); 

    for(i=0; i<n; i++)  buf[i] = toupper(buf[i]);

    send(s,buf,n,0);

  }

}

客户端

#include<stdio.h>

#include<string.h>

#include<strings.h>

#include<sys/types.h>

#include<sys/socket.h>

#include<netinet/in.h>

#include<arpa/inet.h>

 

#define SERV_HOST_ADDR "127.0.0.1"

#define SERV_TCP_PORT 6601

 

int main()

{

  int sockfd,n;

  struct sockaddr_in sa;

  char sendline[512],buf[512];

 

  sockfd = socket(AF_INET, SOCK_STREAM, 0);

 

  bzero((char *)&sa, sizeof(sa));

  sa.sin_family = AF_INET;

  sa.sin_addr.s_addr=inet_addr(SERV_HOST_ADDR);

  sa.sin_port=htons(SERV_TCP_PORT);

 

  connect(sockfd, (struct sockaddr *) &sa, sizeof(sa));

  printf("Connected\n");

  for(;;){

    fgets(sendline, 512, stdin);

    n = strlen(sendline);

    send(sockfd, sendline,n, 0);

 

    n = recv(sockfd,buf,sizeof(buf),0);

    buf[n] = 0;

    fputs(buf, stdout);  fflush(stdout);

  }

}

执行結果

 ./client.exe

 aaa

AAA

bbb

BBB

 

./serve.exe

AAA

BBB

另外  在linux可以用

#  netstat -an | grep 6601

tcp        0      0 0.0.0.0:6601            0.0.0.0:*               LISTEN     

tcp        0      0 127.0.0.1:6601          127.0.0.1:34165         ESTABLISHED

tcp        0      0 127.0.0.1:34165         127.0.0.1:6601          ESTABLISHED

来显示连接

===================================================================

上面的程序是 一对一通信的,下面提升下难度

利用fork函数 一个服务器端与多个客户端进行通信(fork用法不再介绍)

同样是 一个输入小写字符 返回大写字符

服务器端

#include <stdio.h>

#include <stdlib.h>

#include<string.h>

#include<strings.h>

#include<sys/types.h>

#include<sys/socket.h>

#include<netinet/in.h>

#include<arpa/inet.h>

 

#define SERV_TCP_PORT 6601

#define EXIT_FAILURE 1

 

int main()

{

  int sockfd,len,s,n,i;

  struct sockaddr_in sa,ca;

  char buf[512];

  

  sockfd = socket(AF_INET,SOCK_STREAM,0);

  sa.sin_family = AF_INET;

  sa.sin_addr.s_addr = htonl(INADDR_ANY);

  sa.sin_port = htons(SERV_TCP_PORT);

n = bind(sockfd, (struct sockaddr *) &sa, sizeof(sa));

 

  if(n == -1){

    perror("bind");  exit(EXIT_FAILURE);

  }

  listen(sockfd,5);

while(1){

   len = sizeof(ca);

   s = accept(sockfd, (struct sockaddr *) &ca, (socklen_t *) &len);

   printf("Connected\n");

  if(fork()!= 0){

      close(s); 

      continue;

   }

 

   close(sockfd);

printf("Connected from %s port %u\n", inet_ntoa(ca.sin_addr),ntohs(ca.sin_port));

   for(;;){

    n=recv(s,buf,sizeof(buf),0);

if(n == 0){

close(socket);

return 0;

}

 buf[n]=0;

    fputs(buf,stdout);  fflush(stdout);

    for(i=0;i<n;i++)  buf[i]=toupper(buf[i]);

    send(s,buf,n,0);

   }

  }

}

客户端不需要改变   

执行结果

 

#  ./client4_1

Connected

aaaaa

AAAAA

#  ./client4_1

Connected

bbbbb

BBBBB 

#  ./server4_4

Connected

Connected from 127.0.0.1 port 34161

aaaaa

Connected

Connected from 127.0.0.1 port 34162

bbbbb      

     

 

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值