一.什么是socket:
1.socket起源于Unix,都可以用“打开open –> 读写write/read –> 关闭close”模式来操作。Socket就是该模式的一个实现,socket即是一种特殊的文件,一些socket函数就是对其进行的操作(读/写IO、打开、关闭)。
2.Socke可以看成是两个网络应用程序进行通信时,各自通信连接中的端点,这是一个逻辑上的概念。它是网络环境中进程间通信的API(应用程序编程接口),也是可以被命名和寻址的通信端点,使用中的每一个套接字都有其类型和一个与之相连进程。通信时其中一个网络应用程序将要传输的一段信息写入它所在主机的 Socket中,该 Socket通过与网络接口卡(NIC)相连的传输介质将这段信息送到另外一台主机的 Socket中,使对方能够接收到这段信息。 Socket是由IP地址和端口结合的,提供向应用层进程传送数据包的机制。
二.socket服务器和客户端的开发步骤:
1.创建套接字
2.为套接字添加信息(IP地址,端口号)
3.监听网络连接
4.监听到有客户接入,接受一个连接
5.数据交互
6.关闭套接字,断开连接
三.API介绍:
创建套接字:socket
原型:
int socket(int domain,int type,int protocol);
第一个参数是选择协议族:
AF_INET(IPV4)、AF_INET6(IPV6)、AF_LOCAL(或称AF_UNIX,Unix域socket)、AF_ROUTE
我们一般选用AF_INET
第二个参数是选择socket类型,
有SOCK_STREAM、SOCK_DGRAM、SOCK_RAW、SOCK_PACKET、SOCK_SEQPACKET
我们一般选择SOCK_STREAM
第三个参数我们填0就行,内核会根据前两个参数分配。
示例:
socket(AF_INET,SOCK_STREAM,0);
IP,端口号以及相应字符赋值函数:bind
原型:
int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
第一个参数是套接字的描述符,第二个是一个结构体来给套接字的各种变量赋值,Ipv4对应的是
struct sockaddr_in {
sa_family_t sin_family; /* address family: AF_INET */
in_port_t sin_port; /* port in network byte order 2字节*/
struct in_addr sin_addr; /* internet address 4字节*/
unsigned char sin_zero[8];
};
第三个是结构体的大小
示例:
struct sockaddr_in s_addr;
s_addr.sin_family=AF_INET;
s_addr.sin_port=htons(8888);
s_fd=socket(AF_INET,SOCK_STREAM,0);
bind(s_fd,(struct sockaddr *)&s_addr,sizeof(struct sockaddr_in));
地址转换:
int inet_aton(const char* stradr,struct in_addr *addrp);
//字符串形式的“192.168.1.123”转化为网络能识别的格式
char* inet_ntoa(struct in_addr inaddr);
//网络格式->s\字符串格式
示例:
char *ip="192.168.0.11"
inet_aton(ip,&s_addr.sin_addr);
inet_ntoa(c_addr.sin_addr)
监听:listen
原型:
int listen(int sockfd, int backlog);
第一个参数是描述符,第二个是最大允许客户端量(不管是否接入成功)
示例:
listen(s_fd,10);
连接:accept,connect
原型:
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
第一个参数,描述符,第二个客户端信息结构体地址,第三个结构体大小
示例:
accept(s_fd,(struct sockaddr *)&c_addr,&clen);
原型:
int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
第一个参数是描述符,第二个是客户端信息结构体地址,第三个是结构体大小
示例:
connect(c_fd,(struct sockaddr *)&c_addr,sizeof(struct sockaddr)
应用场景:
创立一个socket的服务器,客户端连接后可以实现与客户端互相发送消息。
来看一下代码:
服务器:
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<stdlib.h>
#include<stdio.h>
#include<string.h>
int main(int argc,char **argv)
{
int s_fd;
int c_fd;
int n_read;
char readBuf[128]={0};
char msg[128]={0};
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));
s_fd=socket(AF_INET,SOCK_STREAM,0);
if(s_fd ==-1){
perror("socket");
exit(-1);
}
s_addr.sin_family=AF_INET;
s_addr.sin_port=htons(atoi(argv[2]));
inet_aton(argv[1],&s_addr.sin_addr);
bind(s_fd,(struct sockaddr *)&s_addr,sizeof(struct sockaddr_in));
listen(s_fd,10);
int clen=sizeof(struct sockaddr_in);
while(1){
c_fd =accept(s_fd,(struct sockaddr *)&c_addr,&clen);
if(c_fd ==-1){
perror("accept");
}
else{
printf("get connect :%s\n",inet_ntoa(c_addr.sin_addr));
}
if(fork()==0){
if(fork()==0){
while(1){
memset(msg,0,sizeof(msg));
gets(msg);
write(c_fd,msg,strlen(msg));
}
}
while(1){
memset(readBuf,0,sizeof(readBuf));
n_read=read(c_fd,readBuf,128);
if(n_read==-1){
perror("read");
}else{
printf("get message:%dbyte,%s\n",n_read,readBuf);
}
}
break;
}
}
return 0;
}
~
客户端代码:
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<stdlib.h>
#include<stdio.h>
#include<string.h>
int main(int argc,char **argv)
{
int c_fd;
int n_read;
char readBuf[128];
char msg[128]={0};
struct sockaddr_in c_addr;
memset(&c_addr,0,sizeof(struct sockaddr_in));
c_fd=socket(AF_INET,SOCK_STREAM,0);
if(c_fd ==-1){
perror("socket");
exit(-1);
}
c_addr.sin_family=AF_INET;
c_addr.sin_port=htons(atoi(argv[2]));
inet_aton(argv[1],&c_addr.sin_addr);
if(connect(c_fd,(struct sockaddr *)&c_addr,sizeof(struct sockaddr))==-1){
perror("connect");
exit(-1);
}
while(1){
if(fork()==0){
while(1){
memset(msg,0,sizeof(msg));
gets(msg);
write(c_fd,msg,strlen(msg));
}
}
while(1)
{
n_read=read(c_fd,readBuf,128);
if(n_read==-1){
perror("read");
}else{
printf("get message from sever:%dbyte,%s\n",n_read,readBuf);
}
}
}
return 0;
}~ ~ ~ ~
这里要注意每次写入之前都要清空消息,不然就会有叠加。
来看一下运行结果:
以上就是关于Linux–socket网络编程的介绍。尚有不足之处,请各位大师指正。
salute CLC