Linux系统编程—网络编程

我们在进程间通信的学习过程中了解到,进程间的通信方式有无名管道,FIFO有名管道,消息队列,共享内存,信号量等等,但这些通信方式都是依赖于Linux内核,无法实现不同主机之间的通信,而这时就需要借助网络进行通信。

而在网络编程之前我们要先了解一些基本概念:
IP地址:IP即不同主机设备在以太网的位置
端口号:表示不同主机之间通信服务方式
字节序:字节序是指多字节数据在计算机内存中存储或网络传输时各字节的存储顺序
小端字节序:低序字节存储在起始地址
大端字节序:将高序字节存储在起始地址

SOCKET网络编程(套接字网络编程)

TCP与UDP协议的区别

1,TCP面向连接(即通信之前要先建立连接)UDP是无连接的,即发送数据之前,不需要建立连接
2,TCP提供可靠的服务。UDP是尽最大努力交付,即不保证可靠交付
3,TCP面向字节流,实际上是TCP把数据看成一连串无结构的字节流,UDP是面向报文的,没有拥塞控制
4,每一条TCP连接只能说点到点的 UDP支持一对一,一对多,多对一和多对多的交互通信
5,TCP首部开销20字节;UDP的首部开销小,只有8个字节
6,TCP的逻辑通信信道是全双工的可靠信道,UDP则是不可靠信道

SOCKET服务器和客户端的开发步骤
在这里插入图片描述

常用API

SOCKET()指定协议类型

int socket(int domain, int type, int protocal);

domain:指明所使用的协议族
type:指定socket的类型
protocal:通常赋值为“0”

bind()IP端口号与相应描述子赋值函数

#include <sys/types.h>
#include <sys/socket.h>
int bind(int sockft, const struct sockaddr *addr, socklen_t addrlen);

sockft:是一个socket描述符
addr:是一个指向含有本机IP地址及端口号等信息的sockaddr类型的指针,指向要给绑定给sockfd的协议地址结构,这个结构根据地址创建socket时的地址协议族的不同而不同

结构体:

struct sockaddr{
    unsigned short as_family;
    char  sa_data[14];
};

同等替换
struct sockaddr_in{
     sa_family_t   sin_family:
     in_port_t     sin_port;
     struct in_addr sin_addr;
     unsigned char sin_zero[8];
};

地址转换

int inet_aton(const char* straddr,struct in_addr *addrp);
//把字符串形式的IP地址转为网络能识别的格式

char* inet_ntoa(struct in_addr inaddr);
//把网络格式的IP地址转为字符串形式

listen()函数:监听设置函数

#include <sys/types.h>
#include <sys/socket.h>
int listen(int sockfd, int backlog);

功能:
设置能处理的最大连接数,listen()并未开始接受连线,只是设置socket的listen模式,listen函数只用于服务器端,服务器进程不知道要和谁连接,因此,它不会主动地要求与某个进程连接,只是一直监听是否有其他客户进程与之连接,然后响应连接请求,并对 它做出处理,一个服务进程可以同时处理多个客户进程的连接。

参数:
sockfd是 socket系统调用返回的服务器socket描述符
backlog指定在请求队列中允许的最大请求数

accept()函数

#include <sys/types.h>
#include <sys/socket.h>
int accept(int sockfd, struct sockaddr *addr, socklen_t *addlen);

功能:
accept 函数由 TCP服务器调用,用于从以完成连接队列头返回下一个已完成连接。若接受队列为空那么进程被投入睡眠

参数:
sockfd:是socket系统调用返回的socket描述符
addr:用来返回已连接的客户端的协议地址
addrled:客户端地址长度

connect()客户端连接函数

#include <sys/types.h>
#include <sys/socket.h>
int connect(int sockfd, const struct sockaddr *addr,socklen_t addrlen);

功能:
用于绑定之后的客户端,与服务器建立连接
参数:
sockfd:目的服务器的socket描述符
addr:是服务器端的IP地址和端口号的地址结构指针
addrlen:地址长度常被设置为sizeof(struct sockaddr)

sever服务器的搭建

#include <stdio.h>
#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <stdlib.h>
#include <string.h>

int main()
{
   int s_fd;
   int n_read;
   char readBuf[128];
   char *msg = "i get your connect";
   struct sockaddr_in s_addr;
   struct sockaddr_in c_addr;

   memset(&s_addr,0,sizeof(struct sockaddr_in));
   memset(&c_addr,0,sizeof(struct sockaddr_in));

   //1. socket
   //int socket(int domain, int type, int protocol);
   s_fd = socket(AF_INET, SOCK_STREAM, 0);//ipv4  TCP  
   if(s_fd == -1)
   {
     perror("socket");
     exit(-1);
   }
   s_addr.sin_family = AF_INET;
   c_addr.sin_port = htons(8989);
   inet_aton("127.0.0.1",&s_addr.sin_addr);   
   
   //2. bind
   bind(s_fd,(struct sockaddr *)&s_addr, sizeof(struct sockaddr_in));
   //3. listen
   listen(s_fd,10);
    
   //4. accept
//   int c_fd = accept(s_fd, (struct sockaddr *)&c_addr, NULL);
     int clen = sizeof(struct sockaddr_in);
     int c_fd = accept(s_fd, (struct sockaddr *)&c_addr,&clen);
   if(c_fd == -1){
     perror("accept");
   }
    
    printf("get connect: %s\n",inet_ntoa(c_addr.sin_addr));
   //5. read
   
   n_read = read(c_fd, readBuf, 128);
   if(n_read == -1){
      perror("read");
   }else{
      printf("get message: %d,%s\n",n_read,readBuf);
   }


   //6. write
   write(c_fd,msg,strlen(msg));


   return 0;
}

client客户端搭建

#include <stdio.h>
#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
//#include <linux/in.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <stdlib.h>
#include <string.h>

int main()
{
   int s_fd;
   int n_read;
   char readBuf[128];
   char *msg = "i get your connect";
   struct sockaddr_in c_addr;

   memset(&c_addr,0,sizeof(struct sockaddr_in));

   //1. socket
   c_fd = socket(AF_INET, SOCK_STREAM, 0);//ipv4  TCP  
   if(c_fd == -1)
   {
     perror("socket");
     exit(-1);
   }
   c_addr.sin_family = AF_INET;
   c_addr.sin_port = htons(8989);
   inet_aton("127.0.0.1",&s_addr.sin_addr);   
   
   //2. connect
   if(conect(c_fd,(struct sockaddr)) == -1){
     perror("connect");
     exit(-1);
   } 

   //3. send
   write(c_fd,msg,strlen(msg));
  
    
   if(n_read == -1){
      perror("read");
   }else{
      printf("get message from sever %d,%s\n",n_read,readBuf);
   }


   return 0;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值