赞
踩
网络编程应用于多机通讯,如linux服务器跟安卓手机的通讯,跟ios的手机通讯,跟c51单片绩效的通讯等。
网络编程的要点:
1.地址 (由IP地址跟端口号组成)
每个设备都有一个ip地址来标识。
一台拥有ip地址的主机可以提供许多服务(如web服务,ftp服务等),主机在区分不同的网络服务中显然不能只靠IP地址来区分,还要加上端口号来进行区分。
2.协议(一种数据格式,简单来说就是确定双方交流的语言,不能说一个人讲英语,一个人讲汉语这样双方根本交流不起来)
socket 也叫套接字网络编程主要用 TCP/UDP 的协议 。
TCP/UDP 协议的区别:
TCP面向连接(如打电话你拨号后对方接通建立连接后就可以交流)
UDP是面向报文的(如发短息 ,它只负责发给对方,至于对方看没看到信息它不管)
每一条TCP连接只能点到点的,UDP支持一对一,一对多,多对一,多对多的交互通信
socket网络编程步骤:
创建套接字
int socket( int domain , int type , int protocol )
domain:指明所使用的协议族,一般为AF_INET
type:指定socket的类型,TCP协议是SOCK_STREAM
protocol:一般为0
把ip地址和端口号绑定到套接字
int bind( int sockfd , const struct sockaddr *addr , socklen_t addrlen )
sockfd:socket函数返回的文件描述符
addr:含有本机IP地址及端口号等信息的指针
addrlen:一般为sizeof(struct sockaddr_in)
addr 一般都是用 struct sockaddr_in 类型来定义
struct sockaddr_in{
sa_family_t sin_family; //地址族(Address Family),也就是地址类型
uint16_t sin_port; //16位的端口号
struct in_addr sin_addr; //32位IP地址char sin_zero[8]; //不使用
};struct in_addr{
in_addr_t s_addr; //32位IPv4地址
};
sin_port 和 sin_addr 都必须是网络字节序,一般可视化的数字都是主机字节序
htons( ) 将端口号由主机字节序转换为网络字节序的整数值。
inet_addr( ) 将字符串的IP地址转化为一个网络字节序的整数值。
atoi ( ) 将把字符串转换成长整型数
监听网络连接
int listen( int sockfd , int backlog )
sockfd:socket函数返回的文件描述符
backlog:指定在请求队列中允许的最大请求数
监听到有客户端接入,接受连接
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
sockfd: socket函数返回的文件描述符
addr: 是一个指向struct sockaddr *的指针,里面有客户端的IP地址和端口号等信息,如果对客户的地址不感兴趣,那么可以把这个值设置为NULL
addrten:用来接受addr的结构的大小,它指明addr结构所占有的字节个数,同样的,它也可以被设置为NULL。
客户端连接服务器
int connect( int sockfd , struct sockaddr *serv_addr , int addrlen )
sockfd: socket函数返回的文件描述符
serv_addr:是包含远端主机IP地址和端口号的指针
addrlen:用来接受 serv_addr 的结构的大小,一般为sizeof(struct sockaddr_in)
- #include<stdio.h>
- #include <sys/types.h> /* See NOTES */
- #include <sys/socket.h>
- #include <netinet/in.h>
- #include <arpa/inet.h>
- #include<string.h>
- #include <unistd.h>
- #include <stdlib.h>
-
- int main(int argc,char** argv)
- {
- int s_fd;
- int c_fd
- struct sockaddr_in s_addr;
- struct sockaddr_in c_addr;
-
- if(argc!=3){
- printf("argc no 3\n");
- exit(-1);
- }
-
- s_fd=socket(AF_INET ,SOCK_STREAM ,0);
- if(s_fd==-1){
- perror("socket");
- }
-
- s_addr.sin_family=AF_INET;
- s_addr.sin_port=htons(atoi(argv[2]));
- s_addr.sin_addr.s_addr=inet_addr(argv[1]);
-
-
- bind(s_fd,(struct sockaddr *)&s_addr,sizeof(struct sockaddr_in));
-
- listen(s_fd,10);
-
- int len=sizeof(struct sockaddr_in);
-
- c_fd=accept(s_fd,(struct sockaddr *)&c_addr,&len);
- if(c_fd==-1){
- perror("reason:");
- }
-
- puts("connected successfully");
- printf("clientIP:%s\n",inet_ntoa(c_addr.sin_addr));
-
-
- return 0;
- }
服务端代码编写好后,可以在window用 telnet 测试一下是否能连接上
连接成功,并输出 window 的IP地址
- #include<stdio.h>
- #include <sys/types.h> /* See NOTES */
- #include <sys/socket.h>
- #include <netinet/in.h>
- #include <arpa/inet.h>
- #include <stdlib.h>
-
- int main(int argc,char** argv)
- {
- int c_fd;
-
- if(argc!=3){
- printf("argc no 3\n");
- exit(-1);
- }
-
- c_fd=socket(AF_INET ,SOCK_STREAM,0);
- if(c_fd==-1){
- perror("socket");
- }
-
- struct sockaddr_in c_addr;
- c_addr.sin_family=AF_INET;
- c_addr.sin_port=htons(atoi(argv[2]));
- s_addr.sin_addr.s_addr=inet_addr(argv[1]);
-
-
- if(connect(c_fd,(struct sockaddr *)&c_addr,sizeof(struct sockaddr_in))==-1){
- perror("connect");
- }
-
-
-
- return 0;
- }
客户端成功连接服务器:
客户端连接服务器后可以通过 read()和 write()或者 recv() 和 send()等进行数据传送
ssize_t read( int fd , void *buf , size_t count ) ssize_t write( int fd , const void *buf , size_t count )fd:指定接收端或发送端套接字描述符
buf:指明一个缓冲区,该缓冲区用来存放 read 接收到的数据 或 write 发送的数据
count:指明buf的长度
ssize_t send( int sockfd , const void *buf , size_t len, int flags ); ssize_t recv( int sockfd , void *buf, size_t len , int flags );fd:指定接收端或发送端套接字描述符
buf:指明一个缓冲区,该缓冲区用来存放 recv 接收到的数据 或 send 发送的数据
len:指明buf的长度
flags:指定调用方式,一般置0
以下以read、write 为例
服务器端:
- #include<stdio.h>
- #include <sys/types.h> /* See NOTES */
- #include <sys/socket.h>
- #include <arpa/inet.h>
- #include <netinet/in.h>
- #include <arpa/inet.h>
- #include <unistd.h>
- #include <stdlib.h>
- #include <string.h>
-
- int main(int argc,char** argv)
- {
- int s_fd;
- int c_fd;
- char readbuf[128]={'\0'};
- struct sockaddr_in s_addr;
- struct sockaddr_in c_addr;
-
- if(argc !=3){
- puts("argc no 3");
- }
-
- s_fd=socket(AF_INET,SOCK_STREAM,0);
-
- s_addr.sin_family=AF_INET;
- s_addr.sin_port=htons(atoi(argv[2]));
- s_addr.sin_addr.s_addr=inet_addr(argv[1]);
-
-
- bind(s_fd,(struct sockaddr *)&s_addr,sizeof(struct sockaddr_in));
-
- listen(s_fd,10);
-
- int len=sizeof(struct sockaddr_in);
- c_fd=accept(s_fd,(struct sockaddr *)&c_addr,&len);
-
- puts("connected successfully");
- printf("clientIP:%s\n",inet_ntoa(c_addr.sin_addr));
-
- while(1){
- read(c_fd,readbuf,sizeof(readbuf));
- printf("%s\n",readbuf);
- memset(readbuf,0,sizeof(readbuf));
- }
-
- return 0;
- }
客户端:
- #include<stdio.h>
- #include <sys/types.h> /* See NOTES */
- #include <sys/socket.h>
- #include <netinet/in.h>
- #include <arpa/inet.h>
- #include <stdlib.h>
- #include <unistd.h>
- # include <string.h>
-
- int main(int argc,char** argv)
- {
- int c_fd;
- int n_write;
- char writebuf[128]={'\0'};
- struct sockaddr_in c_addr;
-
- if(argc!=3){
- printf("argc no 3\n");
- exit(-1);
- }
-
- c_fd=socket(AF_INET ,SOCK_STREAM,0);
- if(c_fd==-1){
- perror("socket");
- }
-
- c_addr.sin_family=AF_INET;
- c_addr.sin_port=htons(atoi(argv[2]));
- s_addr.sin_addr.s_addr=inet_addr(argv[1]);
-
-
- if(connect(c_fd,(struct sockaddr *)&c_addr,sizeof(struct sockaddr_in))==-1){
- perror("connect");
- }
-
- while(1){
- puts("input");
- scanf("%s",writebuf);
- n_write=write(c_fd,writebuf,strlen(writebuf));
- if(n_write==-1){
- puts("write failed");
- exit(-1);
- }
- }
-
- return 0;
- }
数据传送成功:
当要把接收到的数据用 printf()进行输出时不要忘了加\n 否则会输出不正常.
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。