Socket编程
目前较为流行的网络编程模型是客户机/服务器通信模式
客户进程向服务器进程发出要求某种服务的请求,服务器进程响应该请求。如图所示,通常,一个服务器进程会同时为多个客户端进程服务,图中服务器进程B1同时为客户进程A1、A2和B2提供服务。

Socket概述
① 所谓Socket通常也称作“套接字”,用于描述IP地址和端口,是一个通信链的句柄。应用程序通常通过“套接字”向网络发出请求或者应答网络请求。
② Socket是连接运行在网络上的两个程序间的双向通信的端点。
③ 网络通讯其实指的就是Socket间的通讯。
④ 通讯的两端都有Socket,数据在两个Socket之间通过IO来进行传输。
套接字socket的类型
(1)流式套接字(SOCK_STREAM)
提供面向连接、可靠的数据传输服务,数据无差错、无重复的发送,且按发送顺序接收(TCP协议)
(2)数据报式套接字(SOCK_DGRAM)
提供无连接服务,数据包以独立包形式发送,不提供无措保证,数据可能丢失,并且接收顺序混乱(UDP协议)
(3)原始套接字(SOCK_RAM)
套接字(socket)
socket起源于Unix,而Unix/Linux基本哲学之一就是“一切皆文件”,都可以用“打开open –> 读写write/read –> 关闭close”模式来操作。Socket就是该模式的一个实现,socket即是一种特殊的文件,一些socket函数就是对其进行的操作(读/写IO、打开、关闭).说白了Socket是应用层与TCP/IP协议族通信的中间软件抽象层,它是一组接口。在设计模中,Socket其实就是一个门面模式,它把复杂的TCP/IP协议族隐藏在Socket接口后面,对用户来说UNIX 通信工具,一组简单的接口就是全部,让Socket去组织数据,以符合指定的协议。
随着Unix的应用推广,套接字有被引进了windows等操作系统。套接字通常只与同一区域的套接字交换数据,windows socket只支持一个通信区域:网际域(AF_INET),这个域被使用忘记协议簇的通信进程使用。
基于UDP(面向无连接)的socket编程

报式传输:“客户端”,1.socket()函数;2.bind()函数,绑定客户端的地址与端口【网络间通信AF_STREAM】或者路径【进程间通信AF_DGRAM】,以便于后续服务端sendto()函数参数的填写。若服务器端只是收不发数据,即,服务端有recvfrom()函数无sendto()函数,则客户端不需要bind()函数;若服务端要发送数据,即,有sendto()函数,则客户端需要bind()函数;3.客户端sendto()函数参数,填写服务端的地址与端口【网络间通信AF_STREAM】或者服务端路径【进程间通信AF_DGRAM】的结构体地址与结构体长度,服务端必须有bind()函数;4.客户端recvfrom()函数参数,NULL,会自动识别。
报式传输:“服务端”,1.socket()函数;2.bind()函数,绑定客户端的地址与端口【网络间通信AF_STREAM】或者路径【进程间通信AF_DGRAM】,以便于后续客户端sendto()函数参数的填写。若服务器端只是收不发数据,即,服务端有recvfrom()函数无sendto()函数,则客户端不需要bind()函数;3.服务端sendto()函数参数,填写客户端的地址与端口【网络间通信AF_STREAM】或者客户端路径【进程间通信AF_DGRAM】的结构体地址与结构体长度,服务端必须有bind()函数;4.recvfrom()函数参数,NULL,会自动识别。
基于UDP(面向无连接)的socket编程(循环监听)——流式套接字(SOCK_STREAM)
进程间通信AF_UNIX,典型的本地进程间通信
服务器:
#include
#include
#include
#include
int main()
{
int iSocketFD = 0;
int iNewFD = 0;
struct sockaddr_un stLocalAddr = {0};
char acBuf[1024]= {0};
iSocketFD = socket(AF_UNIX, SOCK_STREAM, 0);
if(0 > iSocketFD)
{
printf("创建socket失败!\n");
return 0;
}
stLocalAddr.sun_family = AF_UNIX;
sprintf(stLocalAddr.sun_path, "./xxx");
remove("./xxx");
if(0 > bind(iSocketFD, (void *)&stLocalAddr, sizeof(stLocalAddr)))
{
close(iSocketFD);
printf("绑定地址失败!\n");
return -1;
}
if(0 > listen(iSocketFD, 5))
{
close(iSocketFD);
printf("监听失败!\n");
return -1;
}
while(1)
{
iNewFD = accept(iSocketFD, NULL, NULL);
if(0 > iNewFD)
{
close(iSocketFD);
printf("接收数据失败!\n");
return -1;
}
if(0 > recv(iNewFD, acBuf, sizeof(acBuf), 0))
{
close(iSocketFD);
close(iNewFD);
printf("接收失败!\n");
return -1;
}
else
{
printf("接收到的客户端发来的信息是:%s\n", acBuf);
}
if(0 > send(iNewFD, "服务器", sizeof("服务器"), 0))
{
close(iSocketFD);
close(iNewFD);
printf("发送失败!\n");
return -1;
}
}
return 0;
}
客户端:
#include
#include
#include
#include
int main()
{
int iSocketFD = 0;
struct sockaddr_un stRemoteAddr = {0};
char acBuf[1024] = {0};
iSocketFD = socket(AF_UNIX, SOCK_STREAM, 0);
if(0 > iSocketFD)
{
printf("创建socket失败!\n");
return -1;
}
//填充对端地址
stRemoteAddr.sun_family = AF_UNIX;
sprintf(stRemoteAddr.sun_path,"./xxx"); //注意用sprintf
//注意connect的第二个参数
if(0 > connect(iSocketFD, (void *)&stRemoteAddr, sizeof(stRemoteAddr)))
{
close(iSocketFD);
printf("连接服务器失败!\n");
return -1;
}
if(0 > send(iSocketFD, "客户端", sizeof("客户端"), 0))
{
close(iSocketFD);
printf("发送数据失败!\n");
return -1;
}
if(0 > recv(iSocketFD, acBuf, sizeof(acBuf), 0))
{
close(iSocketFD);
printf("接收数据失败!\n");
return -1;
}
printf("客户端接收到服务器发来的消息是:%s\n", acBuf);
return 0;
}
测试:
1、编译服务器、客户端代码:
[root@localhost unix_stream]# make socket_client_stream
cc socket_client_stream.c -o socket_client_stream
[root@localhost unix_stream]# make socket_server_stream
cc socket_server_stream.c -o socket_server_stream
2、执行服务端代码:
[root@localhost unix_stream]# ./socket_server_stream
接收到的客户端发来的信息是:客户端
接收到的客户端发来的信息是:客户端
3、执行客户端代码:
[root@localhost unix_stream]# ./socket_client_stream
客户端接收到服务器发来的消息是:服务器
[root@localhost unix_stream]# ./socket_client_stream
客户端接收到服务器发来的消息是:服务器
基于UDP(面向无连接)的socket编程——数据报式套接字(SOCK_DGRAM)
进程间通信AF_UNIX,典型的本地进程间通信
服务器:( 循环监听)
#include
#include
#include
#include
int main()
{
int iSocketFD = 0;
int iNewFD = 0;
struct sockaddr_un stLocalAddr = {0};
struct sockaddr_un stRemoteAddr = {0};
char acBuf[1024]= {0};
iSocketFD = socket(AF_UNIX, SOCK_DGRAM, 0);
if(0 > iSocketFD)
{
printf("创建socket失败!\n");
return 0;
}
stLocalAddr.sun_family = AF_UNIX;
sprintf(stLocalAddr.sun_path, "./server");
remove("./server");//绑定之前要删除原来的文件
if(0 > bind(iSocketFD, (void *)&stLocalAddr, sizeof(stLocalAddr)))
{
close(iSocketFD);
printf("绑定地址失败!\n");
return -1;
}
stRemoteAddr.sun_family = AF_UNIX;
sprintf(stRemoteAddr.sun_path, "./client");
while(1)
{
if(0 > recvfrom(iSocketFD, acBuf, sizeof(acBuf), 0, NULL, NULL))
{
close(iSocketFD);
printf("接收失败!\n");
return -1;
}
else
{
printf("接收到的客户端发来的信息是:%s\n", acBuf);
}
if(0 > sendto(iSocketFD, "服务器", sizeof("服务器"), 0, (void *)&stRemoteAddr, sizeof(stRemoteAddr)))
{
close(iSocketFD);
printf("发送失败!\n");
return -1;
}
}
return 0;
}
客户端:
#include
#include
#include
#include
int main()
{
int iSocketFD = 0;
struct sockaddr_un stRemoteAddr = {0};
struct sockaddr_un stLocalAddr = {0};
char acBuf[1024] = {0};
iSocketFD = socket(AF_UNIX, SOCK_DGRAM, 0);
if(0 > iSocketFD)
{
printf("创建socket失败!\n");
return -1;
}
stLocalAddr.sun_family = AF_UNIX;
sprintf(stLocalAddr.sun_path, "./client"); //注意用sprintf
remove("./client"); //绑定之前要删除原来的
if(0 > bind(iSocketFD, (void *)&stLocalAddr, sizeof(stLocalAddr)))
{
printf("绑定地址失败!\n");
return -1;
}
//填充对端地址
//报式传输,只发不收可以不bind,要发要收必须要bind
stRemoteAddr.sun_family = AF_UNIX;
sprintf(stRemoteAddr.sun_path, "./server"); //注意用sprintf
if(0 > sendto(iSocketFD, "客户端", sizeof("客户端"), 0, (void *)&stRemoteAddr, sizeof(stRemoteAddr)))
{
close(iSocketFD);
printf("发送数据失败!\n");
return -1;
}
if(0 > recvfrom(iSocketFD, acBuf, sizeof(acBuf), 0, NULL, NULL))
{
close(iSocketFD);
printf("接收数据失败!\n");
return -1;
}
printf("客户端接收到服务器发来的消息是:%s\n", acBuf);
return 0;
}
测试:
1、编译服务器和客户端:
[root@localhost unix_dgram]# make socket_client_dgram
cc socket_client_dgram.c -o socket_client_dgram
[root@localhost unix_dgram]# make socket_server_dgram
cc socket_server_dgram.c -o socket_server_dgram
2、服务器监听:
[root@localhost unix_dgram]# ./socket_server_dgram
接收到的客户端发来的信息是:客户端
接收到的客户端发来的信息是:客户端
3、客户端连接服务器:
[root@localhost unix_dgram]# ./socket_client_dgram
客户端接收到服务器发来的消息是:服务器
[root@localhost unix_dgram]# ./socket_client_dgram
客户端接收到服务器发来的消息是:服务器
参考链接:
java:
基于TCP/IP和UDP协议的socket编程结构解析:
(编辑:威海站长网)
【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!
|