1.socket���� Դ��
2.Socket编程:listen()函数英文翻译
3.scoket函数
4.recvfrom()çrecvfrom
5.CAsyncSocket大致的函数函数代码为
6.2024年度Linux6.9内核最新源码解读-网络篇-server端-第一步创建--socket
socket���� Դ��
源代码奉上,流程图。源码源码。函数函数。源码源码这个太简单了,函数函数你自己看看。源码源码社区源码iapp。函数函数。源码源码。函数函数。源码源码。函数函数。源码源码
//TCP
//服务器端程序
#include< stdio.h >
#include< stdlib.h >
#include< windows.h >
#include< winsock.h >
#include< string.h >
#pragma comment( lib,函数函数 "ws2_.lib" )
#define PORT
#define BACKLOG
#define TRUE 1
void main( void )
{
int iServerSock;
int iClientSock;
char *buf = "hello, world!\n";
struct sockaddr_in ServerAddr;
struct sockaddr_in ClientAddr;
int sin_size;
WSADATA WSAData;
if( WSAStartup( MAKEWORD( 1, 1 ), &WSAData ) )//初始化
{
printf( "initializationing error!\n" );
WSACleanup( );
exit( 0 );
}
if( ( iServerSock = socket( AF_INET, SOCK_STREAM, 0 ) ) == INVALID_SOCKET )
{
printf( "创建套接字失败!\n" );
WSACleanup( );
exit( 0 );
}
ServerAddr.sin_family = AF_INET;
ServerAddr.sin_port = htons( PORT );//监视的端口号
ServerAddr.sin_addr.s_addr = INADDR_ANY;//本地IP
memset( & ( ServerAddr.sin_zero ), 0, sizeof( ServerAddr.sin_zero ) );
if( bind( iServerSock, ( struct sockaddr * )&ServerAddr, sizeof( struct sockaddr ) ) == -1 )
{
printf( "bind调用失败!\n" );
WSACleanup( );
exit( 0 );
}
if( listen( iServerSock, BACKLOG ) == -1 )
{
printf( "listen调用失败!\n" );
WSACleanup( );
exit( 0 );
}
while( TRUE )
{
sin_size = sizeof( struct sockaddr_in );
iClientSock = accept( iServerSock, ( struct sockaddr * )&ClientAddr, &sin_size );
if( iClientSock == -1 )
{
printf( "accept调用失败!\n" );
WSACleanup( );
exit( 0 );
}
printf( "服务器连接到%s\n", inet_ntoa( ClientAddr.sin_addr ) );
if( send( iClientSock, buf, strlen( buf ), 0 ) == -1 )
{
printf( "send调用失败!" );
closesocket( iClientSock );
WSACleanup( );
exit( 0 );
}
}
}
/////客户端程序
#include< stdio.h >
#include< stdlib.h >
#include< windows.h >
#include< winsock.h >
#include< string.h >
#pragma comment( lib, "ws2_.lib" )
#define PORT
#define BACKLOG
#define TRUE 1
#define MAXDATASIZE
void main( void )
{
int iClientSock;
char buf[ MAXDATASIZE ];
struct sockaddr_in ServerAddr;
int numbytes;
// struct hostent *he;
WSADATA WSAData;
// int sin_size;
/* if( ( he = gethostbyname( "liuys" ) ) == NULL )
{
printf( "gethostbyname调用失败!" );
WSACleanup( );
exit( 0 );
}
*/
if( WSAStartup( MAKEWORD( 1, 1 ), &WSAData ) )//初始化
{
printf( "initializationing error!\n" );
WSACleanup( );
exit( 0 );
}
if( ( iClientSock = socket( AF_INET, SOCK_STREAM, 0 ) ) == INVALID_SOCKET )
{
printf( "创建套接字失败!\n" );
WSACleanup( );
exit( 0 );
}
ServerAddr.sin_family = AF_INET;
ServerAddr.sin_port = htons( PORT );
// ServerAddr.sin_addr = *( ( struct in_addr * )he->h_addr );
ServerAddr.sin_addr.s_addr = inet_addr( "..2." );//记得换IP
memset( &( ServerAddr.sin_zero ), 0, sizeof( ServerAddr.sin_zero ) );
if( connect( iClientSock, ( struct sockaddr * ) & ServerAddr, sizeof( struct sockaddr ) ) == -1 )
{
printf( "connect失败!" );
WSACleanup( );
exit( 0 );
}
numbytes = recv( iClientSock, buf, MAXDATASIZE, 0 );
if( numbytes == -1 )
{
printf( "recv失败!" );
WSACleanup( );
exit( 0 );
}
buf[ numbytes ] = '\0';
printf( "Received: %s", buf );
closesocket( iClientSock );
WSACleanup( );
}
/////UDP
//服务器
#include< stdio.h >
#include< string.h >
#include< winsock.h >
#include< windows.h >
#pragma comment( lib, "ws2_.lib" )
#define PORT
#define BACKLOG
#define TRUE 1
#define MAXDATASIZE
void main( void )
{
int iServerSock;
// int iClientSock;
int addr_len;
int numbytes;
char buf[ MAXDATASIZE ];
struct sockaddr_in ServerAddr;
struct sockaddr_in ClientAddr;
WSADATA WSAData;
if( WSAStartup( MAKEWORD( 1, 1 ), &WSAData ) )
{
printf( "initializationing error!\n" );
WSACleanup( );
exit( 0 );
}
iServerSock = socket( AF_INET, SOCK_DGRAM, 0 );
if( iServerSock == INVALID_SOCKET )
{
printf( "创建套接字失败!\n" );
WSACleanup( );
exit( 0 );
}
ServerAddr.sin_family = AF_INET;
ServerAddr.sin_port = htons( PORT );//监视的端口号
ServerAddr.sin_addr.s_addr = INADDR_ANY;//本地IP
memset( & ( ServerAddr.sin_zero ), 0, sizeof( ServerAddr.sin_zero ) );
if( bind( iServerSock, ( struct sockaddr * )&ServerAddr, sizeof( struct sockaddr ) ) == -1 )
{
printf( "bind调用失败!\n" );
WSACleanup( );
exit( 0 );
}
addr_len = sizeof( struct sockaddr );
numbytes = recvfrom( iServerSock, buf, MAXDATASIZE, 0, ( struct sockaddr * ) & ClientAddr, &addr_len );
if( numbytes == -1 )
{
printf( "recvfrom调用失败!\n" );
WSACleanup( );
exit( 0 );
}
printf( "got packet from %s\n", inet_ntoa( ClientAddr.sin_addr ) );
printf( "packet is %d bytes long\n", numbytes );
buf[ numbytes ] = '\0';
printf( "packet contains \"%s\"\n", buf );
closesocket( iServerSock );
WSACleanup( );
}
//客户端
#include< stdio.h >
#include< stdlib.h >
#include< windows.h >
#include< winsock.h >
#include< string.h >
#pragma comment( lib, "ws2_.lib" )
#define PORT
#define MAXDATASIZE
void main( void )
{
int iClientSock;
struct sockaddr_in ServerAddr;
int numbytes;
char buf[ MAXDATASIZE ] = { 0 };
WSADATA WSAData;
if( WSAStartup( MAKEWORD( 1, 1 ), &WSAData ) )
{
printf( "initializationing error!\n" );
WSACleanup( );
exit( 0 );
}
if( ( iClientSock = socket( AF_INET, SOCK_DGRAM, 0 ) ) == -1 )
{
printf( "创建套接字失败!\n" );
WSACleanup( );
exit( 0 );
}
ServerAddr.sin_family = AF_INET;
ServerAddr.sin_port = htons( PORT );
ServerAddr.sin_addr.s_addr = inet_addr( "..2." );//记得换IP
memset( &( ServerAddr.sin_zero ), 0, sizeof( ServerAddr.sin_zero ) );
numbytes = sendto( iClientSock, buf, strlen( buf ), 0, ( struct sockaddr * ) & ServerAddr, sizeof( struct sockaddr ) );
if( numbytes == -1 )
{
printf( "sendto调用失败!\n" );
WSACleanup( );
exit( 0 );
}
printf( "sent %d bytes to %s\n", numbytes, inet_ntoa( ServerAddr.sin_addr ) );
closesocket( iClientSock );
WSACleanup( );
}
Socket编程:listen()函数英文翻译
listen()函数,用于标记一个连接模式的源码源码socket为接收连接状态,并限制接收的函数函数连接队列长度。函数原型为:
#include < sys/socket.h>
int listen(intsocket, int backlog);
其功能为标记一个指定的socket(socket参数)为接收连接模式,并将接收连接的队列长度限制为backlog参数所指定的数量。
如果backlog参数的值小于0,函数将设置socket的监听队列长度为0。在socket的队列中,可能存在未完成的连接,该队列长度可能在内部被实现者增加,以包含这些未完成的phpinfo仅源码连接。
若backlog参数超过了系统依赖的最大队列长度,函数会将socket的监听队列长度设置为最大支持的值。
使用listen()函数可能需要进程具有适当的权限,且返回值为0表示成功,否则返回-1并设置errno以指示错误。
listen()函数可能失败的原因包括:
1. socket参数不是一个有效的文件描述符。
2. socket未绑定到本地地址,且协议不支持在未绑定的socket上监听。
3. socket已经连接。
4. socket参数不引用到socket。
5. 调用进程没有适当的权限。
6. socket已被关闭。
7. 系统中没有足够的资源完成调用。
scoket函数
Socket函数用于创建一个绑定到特定服务提供商的套接字。此函数的原型为:SOCKET socket(
int af,
int type,
int protocol
);
参数说明:af:地址族规范,如IPv4(AF_INET)或IPv6(AF_INET6)。
type:新套接字的类型,Windows Sockets 1.1支持以下两种类型:
SOCK_STREAM:提供有序、可靠的双向连接字节流,支持外在数据传输机制,使用TCP(互联网地址族)。
SOCK_DGRAM:支持无连接、iapp震动源码不可靠的数据报,固定长度(通常较小),使用UDP(互联网地址族)。
protocol:与指定地址族相关的要使用的协议。
返回值:如果没有错误,返回一个引用新套接字的描述符。如果出现错误,将返回INVALID_SOCKET,可以通过WSAGetLastError获取特定错误代码。 常见的错误代码及其含义:WSANOTINITIALISED:在使用此函数前,必须先调用WSAStartup。
WSAE*错误代码(如WSAEAFNOSUPPORT、WSAEINPROGRESS等):表示各种网络问题或操作正在进行中。
套接字函数会分配并绑定到特定的传输-服务提供商。Windows Sockets会使用支持请求的地址族、套接字类型和协议组合的第一个可用服务提供商。创建的套接字默认具有重叠属性。在Microsoft操作系统中,可以使用Mswsock.h中定义的特定于Microsoft的套接字选项SO_OPENTYPE影响这一默认行为,具体请参考Microsoft文档。 没有重叠属性的套接字可以通过WSASocket创建。支持重叠操作的系统保护源码函数(如WSASend、WSARecv等)也支持在重叠套接字上进行非重叠操作,只要与重叠操作相关的参数值为NULL。 在选择协议和服务提供者时,仅会选择基础协议或协议链,而不是单独的协议层。未链接的协议层不会被视为类型或af的匹配部分,即使找不到合适的协议也不会导致WSAEAFNOSUPPORT或WSAEPROTONOSUPPORT错误。 重要提示:虽然AF_UNSPEC常量继续在头文件中定义,但不建议使用,因为它可能导致协议参数值的解析不明确。 面向连接的套接字(如SOCK_STREAM)如TCP,需要处于连接状态才能发送或接收数据。通过connect调用建立与另一个套接字的连接后,使用send和recv进行数据传输。当会话结束时,需要调用closesocket。 面向消息的无连接套接字(如SOCK_DGRAM)支持向任意对端发送和接收数据报,分别使用sendto和recvfrom。若与特定对端连接,可以使用send向其发送数据报,而仅能通过recv从该对端接收。 服务提供商鼓励支持SOCK_RAW类型的自助登记源码套接字,但并非强制要求。对于红外数据自动识别(IrDA)套接字,需明确包含Af_irda.h头文件,仅支持SOCK_STREAM类型,协议参数始终为0。在Windows NT上,raw套接字支持需要管理员权限。 兼容性要求:Windows NT//XP:从Windows NT 3.1及更高版本开始支持。Windows //Me:从Windows 及更高版本开始支持。 头文件:在Winsock2.h中声明。 库:使用Ws2_.lib。 更多信息请查阅:Windows Sockets编程概述、套接字函数、accept、bind、connect、getsockname、getsockopt、ioctlsocket、listen、recv、recvfrom、select、send、sendto、setsockopt、shutdown、WSASocket等。recvfrom()çrecvfrom
recvfromã recvfromå½æ°(ç»socketæ¥æ¶æ°æ®):å½æ°åå:int recvfrom(SOCKET s,void *buf,int len,unsigned int flags, struct sockaddr *from,int *fromlen);
ç¸å ³å½æ° recvï¼recvmsgï¼sendï¼sendtoï¼socket
å½æ°è¯´æ:recv()ç¨æ¥æ¥æ¶è¿ç¨ä¸»æºç»æå®çsocketä¼ æ¥çæ°æ®,并ææ°æ®ä¼ å°ç±åæ°bufæåçå å空é´,åæ°len为å¯æ¥æ¶æ°æ®çæ大é¿åº¦.åæ°flagsä¸è¬è®¾0,å ¶ä»æ°å¼å®ä¹åèrecv().åæ°fromç¨æ¥æå®æ¬²ä¼ éçç½ç»å°å,ç»æsockaddr请åèbind()å½æ°.åæ°fromlen为sockaddrçç»æé¿åº¦.
è¿åå¼:æååè¿åæ¥æ¶å°çå符æ°,失败è¿å-1.
é误代ç
EBADF åæ°séåæ³çsocketå¤ç代ç
EFAULT åæ°ä¸æä¸æéæåæ æ³ååçå å空é´ã
ENOTSOCK åæ°s为ä¸æ件æè¿°è¯ï¼ésocketã
EINTR 被信å·æä¸æã
EAGAIN æ¤å¨ä½ä¼ä»¤è¿ç¨é»æï¼ä½åæ°sçsocket为ä¸å¯é»æã
ENOBUFS ç³»ç»çç¼å²å åä¸è¶³
ENOMEM æ ¸å¿å åä¸è¶³
EINVAL ä¼ ç»ç³»ç»è°ç¨çåæ°ä¸æ£ç¡®ã
èä¾
/*å©ç¨socketçUDP client
æ¤ç¨åºä¼è¿çº¿UDP serverï¼å¹¶å°é®çè¾å ¥çåç¬¦ä¸²ä¼ ç»serverã
UDP server èä¾è¯·åèsendtoï¼ï¼ã
*/
#include<sys/stat.h>
#include<fcntl.h>
#include<unistd.h>
#include<sys/typs.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#define PORT
#define SERVER_IP â.0.0.1â
main()
{
int s,len;
struct sockaddr_in addr;
int addr_len =sizeof(struct sockaddr_in);
char buffer[];
/* 建ç«socket*/
if((s = socket(AF_INET,SOCK_DGRAM,0))<0){
perror(âsocketâ);
exit(1);
}
/* å¡«åsockaddr_in*/
bzero(&addr,sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_port = htons(PORT);
addr.sin_addr.s_addr = inet_addr(SERVER_IP);
while(1){
bzero(buffer,sizeof(buffer));
/* ä»æ åè¾å ¥è®¾å¤åå¾å符串*/
len =read(STDIN_FILENO,buffer,sizeof(buffer));
/* å°åç¬¦ä¸²ä¼ éç»server端*/
sendto(s,buffer,len,0,&addr,addr_len);
/* æ¥æ¶server端è¿åçå符串*/
len = recvfrom(s,buffer,sizeof(buffer),0,&addr,&addr_len);
printf(âreceive: %sâ,buffer);
}
}
æ§è¡ (å æ§è¡udp server åæ§è¡udp client)
hello /*ä»é®çè¾å ¥å符串*/
receive: hello /*server端è¿åæ¥çå符串*/
CAsyncSocket大致的代码为
CAsyncSocket类的创建函数首先通过socket函数创建一个Socket对象,指定关心的Socket事件参数lEvent。然后,它创建一个CSocketWnd对象,这个窗口会在AfxSockInit初始化时被创建,并通过WSAAsyncSelect函数将Socket事件与窗口的WM_SOCKET_NOTIFY消息关联起来。 当Socket事件发生时,会触发CAsyncSocket的DoCallBack函数。这个函数接收Socket句柄(wParam)和错误码(lParam),根据WSAGETSELECTEVENT的结果执行相应的操作,如OnReceive、OnSend、OnOutOfBandData、OnAccept、OnConnect或OnClose。 对于CAsyncSocket的使用,初学者可能会遇到一个常见的误解。当调用CAsyncSocket::Connect()时,可能返回WSAEWOULDBLOCK错误,这并不表示错误,而是由于非阻塞Socket模式,连接需要时间。正确的做法不是立即检查错误,而是调用Connect后,等待OnConnect事件触发。OnConnect会通知我们连接成功或失败,这样能更直观地了解Socket状态。 同样,Send()和Receive()如果返回WSAEWOULDBLOCK,应在相应的OnSend和OnReceive函数中等待,而不是频繁检查错误。这样,程序能更流畅地处理Socket操作,避免不必要的错误检查和调试。扩展资料
它是一个异步非阻塞Socket封装类,CAsyncSocket::Create()有一个参数指明了你想要处理哪些Socket事件,你关心的事件被指定以后,这个Socket默认就被用作了异步方式。CAsyncSocket的Create()函数,除了创建了一个SOCKET以外,还创建了个CSocketWnd窗口对象,并使用WSAAsyncSelect()将这个SOCKET与该窗口对象关联,以让该窗口对象处理来自Socket的事件(消息),然而CSocketWnd收到Socket事件之后,只是简单地回调CAsyncSocket::OnReceive()等虚函数。所以CAsyncSocket的派生类,只需要在这些虚函数里添加发送和接收的代码。年度Linux6.9内核最新源码解读-网络篇-server端-第一步创建--socket
深入解析年Linux 6.9内核的网络篇,从服务端的第一步:创建socket开始。理解用户空间与内核空间的交互至关重要。当我们在用户程序中调用socket(AF_INET, SOCK_STREAM, 0),实际上是触发了从用户空间到内核空间的系统调用sys_socket(),这是创建网络连接的关键步骤。 首先,让我们关注sys_socket函数。这个函数在net/socket.c文件的位置,无论内核版本如何,都会调用__sys_socket_create函数来实际创建套接字,它接受地址族、类型、协议和结果指针。创建失败时,会返回错误指针。 在socket创建过程中,参数解析至关重要:网络命名空间(net):隔离网络环境,每个空间有自己的配置,如IP地址和路由。
协议族(family):如IPv4(AF_INET)或IPv6(AF_INET6)。
套接字类型(type):如流式(SOCK_STREAM)或数据报(SOCK_DGRAM)。
协议(protocol):如TCP(IPPROTO_TCP)或UDP(IPPROTO_UDP),默认值自动选择。
结果指针(res):指向新创建的socket结构体。
内核标志(kern):区分用户空间和内核空间的socket。
__sock_create函数处理创建逻辑,调用sock_map_fd映射文件描述符,支持O_CLOEXEC和O_NONBLOCK选项。每个网络协议族有其特有的create函数,如inet_create处理IPv4 TCP创建。 在内核中,安全模块如LSM会通过security_socket_create进行安全检查。sock_alloc负责内存分配和socket结构初始化,协议族注册和动态加载在必要时进行。RCU机制保护数据一致性,确保在多线程环境中操作的正确性。 理解socket_wq结构体对于异步IO至关重要,它协助socket管理等待队列和通知。例如,在TCP协议族的inet_create函数中,会根据用户请求找到匹配的协议,并设置相关的操作集和数据结构。 通过源码,我们可以看到socket和sock结构体的关系,前者是用户空间操作的抽象,后者是内核处理网络连接的实体。理解这些细节有助于我们更好地编写C++网络程序。 此外,原始套接字(如TCP、UDP和CMP)的应用示例,以及对不同协议的深入理解,如常用的IP协议、专用协议和实验性协议,是进一步学习和实践的重要部分。