分为发送和接受:
发送:
首先,socketAPI会创建并把数据至一个叫sk_buff的结构体,然后依次把sk_buff交给运输层,网络层,数据链路层协议进行处理,然后在填写完sk_buff后再把他交付给驱动程序由网络设备发送出去。
接受和发送是反过程,驱动层程序一般由中断处理收到数据包后会创建sk_buff结构体,让后把数据和一些控制信息填进去,再把sk_buff向数据链路层协议交付,然后就是网络层,运输层最后交给socketAPI接口了
这是在网上找到的,希望对你有所帮助。
sockets(套接字)编程有三种,流式套接字(SOCK_STREAM),数据报套接字(SOCK_DGRAM),原始套接字(SOCK_RAW);
WINDOWS环境下TCP/UDP编程步骤:
1 基于TCP的socket编程是采用的流式套接字。
在这个程序中,将两个工程添加到一个工作区。要链接一个ws2_32lib的库文件。
服务器端编程的步骤:
1:加载套接字库,创建套接字(WSAStartup()/socket());
2:绑定套接字到一个IP地址和一个端口上(bind());
3:将套接字设置为监听模式等待连接请求(listen());
4:请求到来后,接受连接请求,返回一个新的对应于此次连接的套接字(accept());
5:用返回的套接字和客户端进行通信(send()/recv());
6:返回,等待另一连接请求;
7:关闭套接字,关闭加载的套接字库(closesocket()/WSACleanup())。
服务器端代码如下:
#include <stdioh>
#include <Winsock2h>
void main()
{
WORD wVersionRequested;
WSADATA wsaData;
int err;
wVersionRequested = MAKEWORD( 1, 1 );
err = WSAStartup( wVersionRequested, &wsaData );
if ( err != 0 ) {
return;
}
if ( LOBYTE( wsaDatawVersion ) != 1 ||
HIBYTE( wsaDatawVersion ) != 1 ) {
WSACleanup( );
return;
}
SOCKET sockSrv=socket(AF_INET,SOCK_STREAM,0);
SOCKADDR_IN addrSrv;
addrSrvsin_addrS_unS_addr=htonl(INADDR_ANY);
addrSrvsin_family=AF_INET;
addrSrvsin_port=htons(6000);
bind(sockSrv,(SOCKADDR)&addrSrv,sizeof(SOCKADDR));
listen(sockSrv,5);
SOCKADDR_IN addrClient;
int len=sizeof(SOCKADDR);
while(1)
{
SOCKET sockConn=accept(sockSrv,(SOCKADDR)&addrClient,&len);
char sendBuf[50];
sprintf(sendBuf,"Welcome %s to here!",inet_ntoa(addrClientsin_addr));
send(sockConn,sendBuf,strlen(sendBuf)+1,0);
char recvBuf[50];
recv(sockConn,recvBuf,50,0);
printf("%s\n",recvBuf);
closesocket(sockConn);
}
}
客户端编程的步骤:
1:加载套接字库,创建套接字(WSAStartup()/socket());
2:向服务器发出连接请求(connect());
3:和服务器端进行通信(send()/recv());
4:关闭套接字,关闭加载的套接字库(closesocket()/WSACleanup())。
客户端的代码如下:
#include <stdioh>
#include <Winsock2h>
void main()
{
WORD wVersionRequested;
WSADATA wsaData;
int err;
wVersionRequested = MAKEWORD( 1, 1 );
err = WSAStartup( wVersionRequested, &wsaData );
if ( err != 0 ) {
return;
}
if ( LOBYTE( wsaDatawVersion ) != 1 ||
HIBYTE( wsaDatawVersion ) != 1 ) {
WSACleanup( );
return;
}
SOCKET sockClient=socket(AF_INET,SOCK_STREAM,0);
SOCKADDR_IN addrSrv;
addrSrvsin_addrS_unS_addr=inet_addr("127001");
addrSrvsin_family=AF_INET;
addrSrvsin_port=htons(6000);
connect(sockClient,(SOCKADDR)&addrSrv,sizeof(SOCKADDR));
char recvBuf[50];
recv(sockClient,recvBuf,50,0);
printf("%s\n",recvBuf);
send(sockClient,"hello",strlen("hello")+1,0);
closesocket(sockClient);
WSACleanup();
}
2基于UDP的socket编程是采用的数据报套接字。
在这个程序中,将两个工程添加到一个工作区。同时还要链接一个ws2_32lib的库文件。
服务器端编程的步骤:
1:加载套接字库,创建套接字(WSAStartup()/socket());
2:绑定套接字到一个IP地址和一个端口上(bind());
3:等待和接收数据(sendto()/recvfrom());
4:关闭套接字,关闭加载的套接字库(closesocket()/WSACleanup())。
服务器端代码如下:
#include <winsock2h>
#include <stdioh>
void main()
{
WORD wVersionRequested;
WSADATA wsaData;
int err;
wVersionRequested = MAKEWORD( 1, 1 );
err = WSAStartup( wVersionRequested, &wsaData );
if ( err != 0 )
{
return;
}
if ( LOBYTE( wsaDatawVersion ) != 1 ||
HIBYTE( wsaDatawVersion ) != 1 )
{
WSACleanup( );
return;
}
SOCKET sockSrv=socket(AF_INET,SOCK_DGRAM,0);
SOCKADDR_IN addrSrv;
addrSrvsin_addrS_unS_addr=htonl(INADDR_ANY);
addrSrvsin_family=AF_INET;
addrSrvsin_port=htons(7003);
bind(sockSrv,(SOCKADDR)&addrSrv,sizeof(SOCKADDR));
char recvBuf[50];
SOCKADDR addrClient;
int len=sizeof(SOCKADDR);
recvfrom(sockSrv,recvBuf,50,0,(SOCKADDR)&addrClient,&len);
printf("%s\n",recvBuf);
closesocket(sockSrv);
WSACleanup();
}
对于基于UDP的socket客户端来说,要进行如下步骤:
1:创建一个套接字(socket);
2:向服务器发送数据(sendto);
3:关闭套接字;
代码如下:
#include <winsock2h>
#include <stdioh>
void main()
{
WORD wVersionRequested;
WSADATA wsaData;
int err;
wVersionRequested = MAKEWORD( 2, 2 );
err = WSAStartup( wVersionRequested, &wsaData );
if ( err != 0 ) {
return;
}
if ( LOBYTE( wsaDatawVersion ) != 2 ||
HIBYTE( wsaDatawVersion ) != 2 ) {
WSACleanup( );
return;
}
SOCKET sockClient=socket(AF_INET,SOCK_DGRAM,0);
SOCKADDR_IN addrClient;
addrClientsin_addrS_unS_addr=inet_addr("127001");
addrClientsin_family=AF_INET;
addrClientsin_port=htons(8889);
SOCKADDR_IN addrSrv;
sendto(sockClient,"hi",3,0,(SOCKADDR)&addrClient,sizeof(SOCKADDR));
}
LINUX环境下TCP/UDP编程步骤:
TCP编程步骤:
一 服务端:
1socket(int domain,int type,int protocol):建立套接字;
2 bind(int sockid,struct sockaddr addrp,socklen_t addrlen):把本机地址和端口跟上一步建立的socket绑定在一起;
3listen(int sockid,int qsize):监听某套接字;
4fd=accept(int sockid,struct sockaddr callerid,socklen_t addrlenp):等待某套接字接收信息;
5recv(int fd,void buf,size_t nbytes,int flags):从套接字接收数据;
6close(fd) 和close(sockid)
二客户端:
1 socket():建立套接字;
2connect(int sockid,struct sockaddr serv_addrp,socklen_t addrlen):连接到服务器;
3 send(int sockfd,const void buf,size_t nbytes,int flags):发送数据到服务器
4 close(sockid);
UDP编程步骤:
一,服务端:
1 socket():同上;
2 bind():同上;
3 recvfrom(int sockfd,voidbuff,size_t nbytes,int flags,struct sockaddrfrom,socklen_taddrlen):在套接字口接收数据,并且记录下接收到的数据来源;一定要注意这里的参数addrlen,它不仅是函数的输出,也是函数的输入!所以要在调用该函数之前对addrlen赋值sizeof(struct sockaddr)。否则返回的地址from将会出错!
4 close(sockfd);
二 客户端:
1 socket();同上;
2 sendto(int sockfd,const voidbuff,size_t nbytes,int flags,const struct sockaddrto,socklen_t addrlen):往指定的地址发送数据;
3 close(sockfd);
关于阻塞和非阻塞概念,可能有些初学编程的人不是很清楚 阻塞是指在函数执行时如果条件不满足,程序将永远停在那条函数那里不在往下执行,而非阻塞则是函数不管条件是否满足都会往下执行例如在通讯过程中,当接收数据的时候,对于阻塞方式,程序将一直等到接收到数据才向下执行,而对于非阻塞方式,不管是否接收到数据,接收函数将被执行过去一个比较完善的程序一般来讲都使用非阻塞的方式来进行原因在于如果采用阻塞方式,程序将停在那里一直等待条件满足,正常情况下是没有问题的,但如果你想停止阻塞的程序,就出现了比较麻烦的问题 对于VC中使用API方式进行的SOCKET编程,需要使用下面的函数来设置阻塞方式和非阻塞方式: ioctlsocket(gListenSocket, FIONBIO,&tBlockMode); //tBlockMode 0--block,1--no block ioctlsocket(gWorkSocket, FIONBIO,&tBlockMode); 注意,在开发server端程序时,这样设置会控制监听socket的accept()函数的阻塞和非阻塞模式,也可以设置工作socket的recv函数的阻塞和非阻塞模式设置了非阻塞模式,可以使用查询方式进行accept和recv函数执行
SERVER端:
--------------------------------------------------------
import javaioDataInputStream;
import javaioDataOutputStream;
import javaioIOException;
import javanetServerSocket;
import javanetSocket;
public class Server extends Thread {
private Socket clientSocket;
public Server(Socket clientSocket) {
thisclientSocket = clientSocket;
}
public void run() {
DataInputStream dis = null;
DataOutputStream dos = null;
try {
dis = new DataInputStream(clientSocketgetInputStream());
dos = new DataOutputStream(clientSocketgetOutputStream());
while (true) {
String temp = disreadUTF();
if ("over"equals(temp)) {
break;
}
doswriteUTF("from server:" + temp);
}
} catch (Exception e) {
eprintStackTrace();
} finally {
try {
if (dis != null) {
disclose();
}
if (dis != null) {
dosclose();
}
if (clientSocket != null) {
clientSocketclose();
}
} catch (IOException e) {
}
}
}
public static void main(String[] args) throws Exception {
ServerSocket ss = new ServerSocket(8008);
while (true) {
Socket clientSocket = ssaccept();
// 针对每个客户端, 启一个Server线程专门处理此客户端的请求。
Server server = new Server(clientSocket);
serverstart();
}
}
}
CLIENT端:
----------------------------------------
import javaioBufferedReader;
import javaioDataInputStream;
import javaioDataOutputStream;
import javaioInputStreamReader;
import javanetSocket;
public class Client {
public static void main(String[] args) throws Exception {
// 输入流1, 从键盘进入Client。
InputStreamReader isr = new InputStreamReader(Systemin);
BufferedReader br = new BufferedReader(isr);
Socket clientSocket = new Socket("127001", 8008);
// 输入流2, 从服务器端进入Client的流对象。
DataInputStream dis = new DataInputStream(clientSocketgetInputStream());
// 输出流, 从Client出去, 到服务器端。
DataOutputStream dos = new DataOutputStream(clientSocketgetOutputStream());
while (true) {
// 从键盘输入读取
String msg = brreadLine();
// 将读取信息发送给服务器端
doswriteUTF(msg);
//输入QUIT退出
if ("QUIT"equals(msg)) {
break;
}
//读取从服务器返回的信息
String temp = disreadUTF();
Systemoutprintln(temp);
}
brclose();
disclose();
dosclose();
clientSocketclose();
}
}
以上就是关于linux中socket是如何调用驱动程序全部的内容,包括:linux中socket是如何调用驱动程序、UDP和Socket通信步骤、VC中使用API编写的socket程序中如何设置阻塞和非阻塞accept,recv等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)