Linux____网络编程基础

来源:互联网 发布:鹏博士数据 编辑:程序博客网 时间:2024/06/08 08:07

——————————Linux网络编程基础——————————\

Linux网络编程课程

第一节:网络编程环境搭建

利用虚拟机在Ubuntu系统上建立用户 制作网络服务器

Linux虚拟机:VMware-workstation-full-9.0.1   安装后建立新的虚拟机下一步后 选择你存储的Ubuntu系统镜像的位置。安装系统镜像后进入管理员模式按照课程内容实现虚拟机的网络连接功能。改写默认文件通过copy课程提供的修改好的文件。

:~$ ctrl+@+t打开操作系统终端

:~$ sudo passwd root 输入三次密码 //使用虚拟机第一次登陆需要建立root用户。使用<——此命令建立

:~$ sudo root//下次登陆时从普通用户切换到root用户

//如果虚拟机不能上网 需要在VM setten里面将网络模式改为net模式。 在服务里面选择VMware DHCP这个服务

//设置Ubuntu系统和Windows共享数据:进入菜单VM——Settings选项——Options——Shared Folders——allways enable——add——next——Browse选择文件夹——


//将老师上传的配置文件复制到共享源下

// 使用cp命令将配置文件拷贝到ubuntu系统下

:/etc/apt# cp /mnt/hgfs/e_share/sources.list./

//接下来使用命令更新源

:/etc/apt# apt-getupdate

//更新源时可能出现Could not get lock xxx/xxx/xx -open(11:Resource tmporarily unavaliable)错误 需要删除临时文件 使用如下命令删除!

:/etc/apt# rm -f /var/lib/apt/lists/*

//然后继续更新


//接下来调用命令安装vim编辑器

:/etc/apt# apt-get install vim


//接下来配置vim编辑器

//调用命令将共享源的vimrc文件拷贝到系统目标文件夹下

:~# cp /mnt/hgfs/e_shared/vimrc ~/.vimrc ^C


//接下来是vim的简单使用 进入vim编辑器

:~# vim

// 单击i 进入编辑模式、单击v进入可视模式(可复制、粘贴、删除)、双击d标示删除当前行、

//v模式下可以选择多行、整块的复制可以单击y、双击y复制当前行、单击p粘贴、单击u恢复


第二节:网络编程基础API

socketAPI:

//cpu累加器一次都能装载4个字节,这4个字节在内存中的排列顺序影响到累加器装载后成的值,这就是字节序的问题。现在PC大都选择小端字节序,当格式化的数据在不同字节序的接收端传递时会出现错误解释。所以解决办法是发送端发出时都是将数据转化成大端字节序。接收端知道接收到的都是大端字节序,根据自身情况选择是否进行转换。

//两个接口完成的是长整形的主机字节序与网络字节序之间的转换

主机字节和网络字节转换API:#include <netinet/in.h>//主机字节转换成网络字节unsigned short int htons(unsigned short int hostshrot);    //网络字节转换成主机字节unsigned short int ntohs(unsigned short int netshrot);



专用socket地址结构体:

//TCP/IP协议族专用socket地址结构体struct sockaddr_in{sa_family_tsin_family; //地址族:AF_INETu_int16_tsin_port; //端口号, 要用网络字节序表示structin_addrsin_addr;//IPv4地址结构体,是u_int32_ts_addr;};


IP转换函数:

#include <arpa/inet.h>//将字符串IP转换为整数IP//将src转换成整数型存储到dst所指向的内存中//第一个参数:地址族 //成功时返回1    失败时返回0int inet_pton(int af, const char* src,void* dst);    //将整数IP转换成字符串IP//最后一个参数cnt指示目标存储单元的大小//成功返回时:目标存储单元的地址//失败时返回null关键字const char* inet_ntop(int af, const void* dst,socklen_t cnt);   


创建socket:

对于linux来说 所有对象都是文件,套接字也不例外,就是可读可写可关闭的操作符

#include <sys/types>#incliude <sys/socket.h>/*domain:底层协议族类型type: 指定服务类型protocol :具体的协议*///第一个参数表示底层使用哪个协议簇,对于TCP/IP协议而言要使用AF_INET或者AF_INET6//第二个参数表示服务类型,有流服务和数据报服务//对于TCP/IP协议而言 传输值socketstream表示传输层使用TCP协议。传输至socketdgram表示使用udp协议。//第三个参数表示在前两个协议下再选择一个具体的协议。这个值通常为0//成功时返回一个socket文件描述符,失败时返回-1int socket(int domain, int type, int protocol);



命名socket:
//将一个socket地址和类型绑定成为给socket命名#include <sys/types>#include <sys/socket.h>// 服务器绑定网络地址//bing将第二个参数所指的socket地址分割给未命名的socket文件描述符。//第三个参数指示的是该socket地址的文件长度//成功时返回0    失败时返回-1int bind(int sockfd, const struct sockeaddr* addr,socketlen_t addrlen);//常见错误类型EACCES:被绑定的地址是收到保护的地址。只有超级用户可以访问。EADDRINUSE:被绑定的地址正在使用中


监听socket:

//创建一个监听队列,用来存放待处理的客户连接。#include <sys/socket.h>//第一个参数指定被监听的socket//第二个参数指定内核监听队列的最大长度//成功时返回0    失败时返回-1int listen(int sockfd,int backlog);


接收连接API:

#include <sys/types.h>#include <sys/socket.h>//accept是从listen监听队列中接收一个连接。//第一个参数是执行过listen系统监听的socket//第二个参数是用来获取被接受连接的远端socket地址//第三个参数socket地址长度//成功时返回一个新的连接socket,通过此socket与被接受连接的客户端进行通信//失败时返回-1.此函数被用于作为服务端使用。int accept(int sockfd,struct sockaddr* addr,socklen_t* addrlen);



发起连接:

//用来主动与服务器建立连接#include <sys/types.h>#include <sys/socket.h>//第一个参数是由socket地址调用返回一个套接字//第二个参数是服务器监听的socket地址//第三个参数指定这个地址的长度//成功时返回0,一旦成功建立连接,socketfd就唯一标识了这个连接。客户端就可以通过读写socketfd来与服务器进行通信int connect(int sockfd,const struct sockaddr* serv_addr,socklen_t addrlen);//常见errno类型:ECONNEFUSED:目标端口不存在ETIMEOUT:连接超时


关闭连接:

//第一种关闭连接方式close#include <unistd.h>#include <sys/socket.h>//关闭socket。并不总是立即关闭,而是将fd的引用次数减一。只有当fd的引用次数为0时才真正关闭连接。int close(int fd);//无论如何立即关闭//第一个参数:带关闭的socket//关闭shutdown的行为int shutdown(int sockfd,int howto);shutdown函数中howto参数选项SHUT_RE:关闭读这一半SHUT_WR:关闭写着一半SHUT_RDWR:同时关闭读和写


TCP数据读写API:

#include <sys/types.h>#include <sys/socket.h>//用于TCP流数据的系统调用方式有recv、send//buf len分别指定读缓冲区的位置和大小 flags通常设置为0//recv成功时返回实际读取到的数据的长度。可能小于我们期望的长度//recv返回0时标志通信对方已经关闭连接//如果出错,则返回-1ssize_t recv(int sockfd,void* buf,size_t len,int flags);//send是往sockfd上写入数据//buf len分别指定写缓冲区的位置和大小//成功时:返回实际写入的数据的长度。失败时:返回-1ssize_t send(int sockfd,cons void* buf,size_t len,int flags);recv函数和send函数的flags参数选项MSG_WAITALL:读操作读取到一定数量字节后返回MSG_PEEK:查看读缓冲中的数据而不取出

UDP数据读写API:
#include <sys/types.h>#include <sys/socket.h>ssize_t recvfrom(int sockfd,void* buf,size_t len,int flags,struct sockaddr* src_addr,socklen_t* addrlen);ssize_t sendto(int sockfd,cons void* buf,size_t len,int flags,const struct sockaddr* dest_addr,sockelen_t addrlen);TCP UDP UDP读写API中多两个字段 一个是读:socket来源地址 长度。写:目标socket地址,长度  flag的几种关键字含义在TCP UDP中都一样。




第三节:服务端、客户端开发流程



~!!所有用到的代码都是前面讲过的

tcpclient.c:

#include <sys/socket.h>#include <netinet/in.h>#include <arpa/inet.h>#include <stdio.h>#include <assert.h>#include <unistd.h>#include <string.h>#include <stdlib.h>int main(int argc,char* argv[]){//从终端输入服务器绑定的socket和端口号if(argc <= 2){printf("please input server ip and port number\r\n");return -1;}const char* ip = argv[1];<span style="white-space:pre"></span>//保存终端传入的ip地址int port = atoi(argv[2]);<span style="white-space:pre"></span>//将传进来的字符串型的端口号转换成整型struct sockaddr_in server_address;<span style="white-space:pre"></span>//声明一个结构体 存储服务器的地址结构信息bzero(&server_address,sizeof(server_address));<span style="white-space:pre"></span>//同时将这个结构体的所有字段都清零server_address.sin_family = AF_INET;<span style="white-space:pre"></span>//体质族字段声明成TCP/IP协议族inet_pton(AF_INET,ip,&server_address.sin_addr);<span style="white-space:pre"></span>//同时将服务器传进来的ip地址存储到地址结构信息中server_address.sin_port = htons(port);<span style="white-space:pre"></span>//将服务器绑定的端口号转化成网络字节存储到地址结构信息中int sockfd = socket(AF_INET,SOCK_STREAM,0);<span style="white-space:pre"></span>//申请一个本地套接字 并使用套接字来连接服务器。两个if判断连接是否成功if(sockfd < 0){printf("socket create failed \r\n");return -1;}if(connect(sockfd,(struct sockaddr*)&server_address,sizeof(server_address))<0){printf("connect failed \r\n");return -1;}else{char data[64]="Where are you from ?";<span style="white-space:pre"></span>//给服务器的数据时where are you fromchar buffer[64];<span style="white-space:pre"></span>//服务器传入的数据存储到buffer这个数组int i,len;for(i=0;i<10;i++)<span style="white-space:pre"></span>//加入和数据库交互十次{memset(buffer,0x00,sizeof(buffer));<span style="white-space:pre"></span>//将接收到的数据存入到buffer中send(sockfd,data,strlen(data),0);<span style="white-space:pre"></span>//给服务器传递数据len = recv(sockfd,buffer,sizeof(buffer),0);sleep(1);printf("index is %d len is %d : %s\r\n",i,len,buffer);<span style="white-space:pre"></span>//将接收到的数据长度存储到len后打印到屏幕中}}close(sockfd);<span style="white-space:pre"></span>//主动关闭连接return 0;}<pre name="code" class="cpp">//最后记得编译文件
vim tcpclient.c
gcc -o tcpclient tcpclient.c

tcpserver.c:
#include <sys/socket.h>#include <netinet/in.h>#include <arpa/inet.h>#include <assert.h>#include <stdio.h>#include <stdlib.h>#include <string.h>int main(int argc,char* argv[]){if(argc <=2 ){printf("please input ipaddress and port number\r\n");return -1;}const char* ip = argv[1];int port = atoi(argv[2]);struct sockaddr_in address;bzero(&address,sizeof(address));address.sin_family = AF_INET;inet_pton(AF_INET,ip,&address.sin_addr);address.sin_port = htons(port);int sock = socket(AF_INET,SOCK_STREAM,0);<span style="white-space:pre"></span><span style="font-family: Arial, Helvetica, sans-serif;">//创建监听套接字</span><span style="white-space:pre"></span>if(sock <0){printf("create sock failed \r\n");return -1;}int ret = bind(sock,(struct sockaddr*)&address,sizeof(address));if(ret == -1){printf("bind failed\r\n");return -1;}ret = listen(sock,5);<span style="white-space:pre"></span>//执行监听?if(ret == -1){printf("listen failed \r\n");return -1;}struct sockaddr_in client;socklen_t client_addrlength = sizeof(client);int connfd = accept(sock,(struct sockaddr*)&client,&client_addrlength);<span style="white-space:pre"></span>//接收连接 返回一个新socketif(connfd < 0)<span style="white-space:pre"></span>//判断连接成功否{printf("accept failed \r\n");}else<span style="white-space:pre"></span>//成功就开始通信{char data[64]="I am from jikexueyuan!";char buffer[64];int i,len;for(i=0;i<10;i++){memset(buffer,0x00,sizeof(buffer));len = recv(connfd,buffer,sizeof(buffer),0);printf("index is %d len is %d: %s\r\n",i,len,buffer);sleep(1);send(connfd,data,strlen(data),0);}close(connfd);<span style="white-space:pre"></span>//关闭监听套接字}close(sock);return 0;}<pre name="code" class="cpp"><pre name="code" class="cpp">//最后记得编译文件
vim tcpserver.c
gcc -o tcpserver tcpserver.c

运行服务器端程序:

root@ubuntu:/home/work# ./tcpserver192.168.80.130 2345 //此时 服务器处于监听状态


运行客户端程序,主动进行连接:

root@xduser:/home/work# ./tcpclient192.168.80.130 2345//会返回十个I am from jikexueyuan!





第四节:UDP服务端/客户端开发过程


udpclient.c:

#include <sys/types.h>#include <sys/socket.h>#include <netinet/in.h>#include <stdlib.h>#include <stdio.h>#include <string.h>#define PORT_SERVER 8888int main(int argc,char* argv[]){int s;struct sockaddr_in addr_server,addr_client;const char* ip = "192.168.80.130";bzero(&addr_server,sizeof(addr_server));inet_pton(AF_INET,ip,&addr_server.sin_addr);addr_server.sin_family = AF_INET;addr_server.sin_port = htons(PORT_SERVER);s = socket(AF_INET,SOCK_DGRAM,0);printf("s is %d \r\n",s);char data[64]="Where are you from ?";char buffer[64];int i;int len = sizeof(addr_server);for(i=0;i<10;i++){memset(buffer,0x00,sizeof(buffer));int ret = sendto(s,data,strlen(data),0,(struct sockaddr*)&addr_server,len);recvfrom(s,buffer,sizeof(buffer),0,(struct sockaddr*)&addr_client,&len);printf("index is %d : %s \r\n",i,buffer);sleep(1);}close(s);return 0;}
udpserver.c

#include <sys/socket.h>#include <sys/types.h>#include <netinet/in.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#define PORT_SERVER 8888<span style="white-space:pre"></span>//规定端口号int main(int argc,char* argv[]){int s;struct sockaddr_in addr_server,addr_client;const char* ip = "192.168.80.130";<span style="white-space:pre"></span>//规定ip地址s = socket(AF_INET,SOCK_DGRAM,0);memset(&addr_server,0x00,sizeof(addr_server));addr_server.sin_family = AF_INET;addr_server.sin_addr.s_addr = htonl(INADDR_ANY);addr_server.sin_port = htons(PORT_SERVER);bind(s,(struct sockaddr*)&addr_server,sizeof(addr_server));char data[64]="I am from jikexueyuan!";char buffer[64];int i;int len = sizeof(addr_server);for(i=0;i<10;i++){memset(buffer,0x00,sizeof(buffer));recvfrom(s,buffer,sizeof(buffer),0,(struct sockaddr*)&addr_client,&len);printf("index is %d : %s \r\n",i,buffer);sendto(s,data,strlen(data),0,(struct sockaddr*)&addr_client,len);sleep(1);}close(s);return 0;}















0 0
原创粉丝点击