socket返回值linux
Ⅰ linux下 socket函數的返回值代表什麼
int socket;domain指明所使用的協議族,通常為PF_INET,表示互聯網協議族;type參數指定socket的類型:SOCK_STREAM 或SOCK_DGRAM,Socket介面還定義了原始Socket,允許程序使用低層協議;protocol通常賦值"0"。
Socket()調用返回一個整型socket描述符,你可以在後面的調用使用它。 Socket描述符是一個指向內部數據結構的指針,它指向描述符表入口。
調用Socket函數時,socket執行體將建立一個Socket,實際上"建立一個Socket"意味著為一個Socket數據結構分配存儲空間。 Socket執行體為你管理描述符表。
(1)socket返回值linux擴展閱讀:
支持下述類型描述:
SOCK_STREAM 提供有序的、可靠的、雙向的和基於連接的位元組流,使用帶外數據傳送機制,為Internet地址族使用TCP。
SOCK_DGRAM 支持無連接的、不可靠的和使用固定大小(通常很小)緩沖區的數據報服務,為Internet地址族使用UDP。
SOCK_STREAM類型的套介面為全雙向的位元組流。對於流類套介面,在接收或發送數據前必需處於已連接狀態。用connect()調用建立與另一套介面的連接,連接成功後,即可用send()和recv()傳送數據。當會話結束後,調用close()。帶外數據根據規定用send()和recv()來接收。
Ⅱ linux手冊翻譯——socket(7)
socket - Linux 套接字介面
本手冊頁描述了 Linux 網路套接字層用戶介面。 套接字是用戶進程和內核中網路協議棧之間的統一介面。 協議模塊分為協議族(protocol families)(如 AF_INET、AF_IPX 和 AF_PACKET)和套接字類型(socket types)(如 SOCK_STREAM 或 SOCK_DGRAM)。 有關families和types的更多信息,請參閱 socket(2) 。
用戶進程使用這些函數來發送或接收數據包以及執行其他套接字操作。 有關更多信息,請參閱它們各自的手冊頁。
socket(2) 創建套接字,connect(2) 將套接字連接到遠程套接字地址,bind(2) 函數將套接字綁定到本地套接字地址,listen(2) 告訴套接字應接受新連接, accept(2) 用於獲取具有新傳入連接的新套接字。 socketpair(2) 返回兩個連接的匿名套接字(僅為少數本地families如 AF_UNIX 實現)
send(2)、sendto(2) 和sendmsg(2) 通過套接字發送數據,而recv(2)、recvfrom(2)、recvmsg(2) 從套接字接收數據。 poll(2) 和 select(2) 等待數據到達或准備好發送數據。 此外,還可以使用 write(2)、writev(2)、sendfile(2)、read(2) 和 readv(2) 等標准 I/O 操作來讀取和寫入數據。
getsockname(2) 返回本地套接字地址, getpeername(2) 返回遠程套接字地址。 getsockopt(2) 和 setsockopt(2) 用於設置或獲取套接字層或協議選項。 ioctl(2) 可用於設置或讀取一些其他選項。
close(2) 用於關閉套接字。 shutdown(2) 關閉全雙工套接字連接的一部分。
套接字不支持使用非零位置查找或調用 pread(2) 或 pwrite(2)。
通過使用 fcntl(2) 在套接字文件描述符上設置 O_NONBLOCK 標志,可以在套接字上執行非阻塞 I/O。 然後所有會阻塞的操作(通常)將返回 EAGAIN(操作應稍後重試); connect(2) 將返回 EINPROGRESS 錯誤。 然後用戶可以通過 poll(2) 或 select(2) 等待各種事件。
如果不使用poll(2) 和 select(2) ,還讓內核通過 SIGIO 信號通知應用程序有關事件的信息。 為此,必須通過 fcntl(2) 在套接字文件描述符上設置 O_ASYNC 標志,並且必須通過 sigaction(2) 安裝有效的 SIGIO 信號處理程序。 請參閱下面的信號討論。
每個套接字域(families)都有自己的套接字地址格式,具有特定於域的地址結構。 這些結構的首欄位都是整數類型的「家族」欄位(類型為 sa_family_t),即指出自己的套接字域或者說是protocol families。 這允許對所有套接字域可以使用統一的系統調用(例如,connect(2)、bind(2)、accept(2)、getsockname(2)、getpeername(2)),並通過套接字地址來確定特定的域。
為了允許將任何類型的套接字地址傳遞給套接字 API 中的介面,定義了類型 struct sockaddr。 這種類型的目的純粹是為了允許將特定於域的套接字地址類型轉換為「通用」類型,以避免編譯器在調用套接字 API 時發出有關類型不匹配的警告。
struct sockaddr 以及在AF_INET常用的地址結構struct sockaddr_in如下所示,sockaddr_in.sin_zero是佔位符:
此外,套接字 API 提供了數據類型 struct sockaddr_storage。 這種類型適合容納所有支持的特定於域的套接字地址結構; 它足夠大並且正確對齊。 (特別是它足夠大,可以容納 IPv6 套接字地址。)同struct sockaddr一樣,該結構體包括以下欄位,可用於標識實際存儲在結構體中的套接字地址的類型: sa_family_t ss_family;
sockaddr_storage 結構在必須以通用方式處理套接字地址的程序中很有用(例如,必須同時處理 IPv4 和 IPv6 套接字地址的程序)。
下面列出的套接字選項可以使用setsockopt(2) 設置並使用getsockopt(2) 讀取。
當寫入已關閉(由本地或遠程端)的面向連接的套接字時,SIGPIPE 被發送到寫入進程並返回 EPIPE。 當寫調用指定 MSG_NOSIGNAL 標志時,不發送信號。
當使用 FIOSETOWN fcntl(2) 或 SIOCSPGRP ioctl(2) 請求時,會在 I/O 事件發生時發送 SIGIO。 可以在信號處理程序中使用 poll(2) 或 select(2) 來找出事件發生在哪個套接字上。 另一種方法(在 Linux 2.2 中)是使用 F_SETSIG fcntl(2) 設置實時信號; 實時信號的處理程序將使用其 siginfo_t 的 si_fd 欄位中的文件描述符調用。 有關更多信息,請參閱 fcntl(2)。
在某些情況下(例如,多個進程訪問單個套接字),當進程對信號做出反應時,導致 SIGIO 的條件可能已經消失。 如果發生這種情況,進程應該再次等待,因為 Linux 稍後會重新發送信號。
核心套接字網路參數可以通過目錄 /proc/sys/net/core/ 中的文件訪問。
These operations can be accessed using ioctl(2):
error = ioctl(ip_socket, ioctl_type, &value_result);
Valid fcntl(2) operations:
Linux assumes that half of the send/receive buffer is used for internal kernel structures; thus the values in the corresponding /proc files are twice what can be observed on the wire. Linux will allow port reuse only with the SO_REUSEADDR option when this option was set both in the previous program that performed a bind(2) to the port and in the program that wants to reuse the port. This differs from some implementations (e.g., FreeBSD) where only the later program needs to set the SO_REUSEADDR option. Typically this difference is invisible, since, for example, a server program is designed to always set this option.
Ⅲ linux socket 如何發現主機是否活著
使用基本socket函數來檢測。
Linux系統是通過提供套接字(socket)來進行網路編程的。網路的socket數據傳輸是一種特殊的I/O,socket也是一種文件描述符。socket也有一個類似於打
開文件的函數:socket(),調用socket(),該函數返回一個整型的socket的描述符,隨後的連接建立、數據傳輸等操作也都是通過該socket實現。
1、socket函數
syntax:
int socket(int domain, int type, int protocol);
功能說明:
調用成功,返回socket文件描述符;失敗,返回-1,並設置errno
參數說明:
domain指明所使用的協議族,通常為PF_INET,表示TCP/IP協議;
type參數指定socket的類型,基本上有三種:數據流套接字、數據報套接字、原始套接字
protocol通常賦值"0"。
兩個網路程序之間的一個網路連接包括五種信息:通信協議、本地協議地址、本地主機埠、遠端主機地址和遠端協議埠。socket數據結構中包含這五種信息。
2、bind函數
syntax:
int bind(int sock_fd,struct sockaddr_in *my_addr, int addrlen);
功能說明:
將套接字和指定的埠相連。成功返回0,否則,返回-1,並置errno.
參數說明:
sock_fd是調用socket函數返回值,
my_addr是一個指向包含有本機IP地址及埠號等信息的sockaddr類型的指針;
struct sockaddr_in結構類型是用來保存socket信息的:
struct sockaddr_in {
short int sin_family;
unsigned short int sin_port;
struct in_addr sin_addr;
unsigned char sin_zero[8];
};
addrlen為sockaddr的長度。
3、connect函數
syntax:
int connect(int sock_fd, struct sockaddr *serv_addr,int addrlen);
功能說明:
客戶端發送服務請求。成功返回0,否則返回-1,並置errno。
參數說明:
sock_fd 是socket函數返回的socket描述符;serv_addr是包含遠端主機IP地址和埠號的指針;addrlen是結構sockaddr_in的長度。
4、listen函數
syntax:
int listen(int sock_fd, int backlog);
功能說明:
等待指定的埠的出現客戶端連接。調用成功返回0,否則,返回-1,並置errno.
參數說明:
sock_fd 是socket()函數返回值;
backlog指定在請求隊列中允許的最大請求數
5、accecpt函數
syntax:
int accept(int sock_fd, struct sockadd_in* addr, int addrlen);
功能說明:
用於接受客戶端的服務請求,成功返回新的套接字描述符,失敗返回-1,並置errno。
參數說明:
sock_fd是被監聽的socket描述符,
addr通常是一個指向sockaddr_in變數的指針,
addrlen是結構sockaddr_in的長度。
6、write函數
syntax:
ssize_t write(int fd,const void *buf,size_t nbytes)
功能說明:
write函數將buf中的nbytes位元組內容寫入文件描述符fd.成功時返回寫的位元組數.失敗時返回-1. 並設置errno變數.
在網路程序中,當我們向套接字文件描述符寫時有倆種可能:
1)write的返回值大於0,表示寫了部分或者是全部的數據.
2)返回的值小於0,此時出現了錯誤.需要根據錯誤類型來處理.
如果錯誤為EINTR表示在寫的時候出現了中斷錯誤.
如果錯誤為EPIPE表示網路連接出現了問題.
7、read函數
syntax:
ssize_t read(int fd,void *buf,size_t nbyte)
函數說明:
read函數是負責從fd中讀取內容.當讀成功時,read返回實際所讀的位元組數,如果返回的值是0 表示已經讀到文件的結束了,小於0表示出現了錯誤.
如果錯誤為EINTR說明讀是由中斷引起的,
如果錯誤是ECONNREST表示網路連接出了問題.
8、close函數
syntax:
int close(sock_fd);
說明:
當所有的數據操作結束以後,你可以調用close()函數來釋放該socket,從而停止在該socket上的任何數據操作:
函數運行成功返回0,否則返回-1
Ⅳ linux 下socket的recv函數返回值問題
說清楚一點,是UDP還是TCP
不管怎麼說,在recv之前調用一下select(),檢查緩沖到底有沒有內容,如果有,再執行recv就不會有任何問題。而且 select的好處是,如果沒有接到別的東西,你可以sleep()一下,不佔用CPU
用下面的rcv代替你的recv函數吧,我在嵌入式系統開發時自己寫的一個標准常式,很可靠:
參數解釋:
sck - socket
buf - 接收緩沖區
size-緩沖區大小
time_out-等待時間(按秒計)如果超時則返回
返回值:收到位元組數,0表示超時等錯誤
int rcv(int sck, void * buf, int size, int time_out)
{
if (sck < 1 || !buf || size < 1) return 0;
timeval tv = { 0, 0}; timeval * ptv = 0;
if (time_out > 0) { tv.tv_sec = time_out; ptv = &tv; }
memset(buf, 0, size);
int r = 0; char * b = (char*) buf; int sz = size;
fd_set rd, er; int total = 0; time_t t0 = time(0); time_t t1 = 0;
do {
FD_ZERO(&rd); FD_SET(sck, &rd);
FD_ZERO(&er); FD_SET(sck, &er);
r = select(sck + 1, &rd, 0, &er, ptv);
if (r == -1) { nperror("select()"); return -1; }
if (FD_ISSET(sck, &er)) {
nperror("socket(shutdown)"); return -1;
}//end if
if (FD_ISSET(sck, &rd)) {
r = recv(sck, b, sz, 0);
if (r == -1) { nperror("recv()"); return -1; }
total += r; sz -= r; b+= r;
}//end if
if (time_out > 0)
t1 = time(0) - t0;
else
t1 = time_out - 1;
//end if
}while(sz && t1 < time_out);
return total;
}//end if
Ⅳ linux socket返回的int值是什麼 文件描述符一樣的東西嗎
socket系統調用返回的int值是一個描述符,這個描述符在許多方面都類似於底層的文件描述符,但是和文件描述符又有一些稍微的區別,比如說socket返回的描述符需要用close調用來關閉(這點和文件描述符一樣),但是close調用關閉這個描述符時還會有一些不同與文件描述符的行為(因為它代表的是一個套接字連接,所以close調用還會關閉套接字連接和未傳輸完數據時阻塞)。
Ⅵ 關於Linux下socket編程的問題
recv 函數,不能保證接受到所有你需要的數據包
因此要反復調用recv函數. 並查看函數的返回值
比如,你需要接受5000位元組
datalen=0
while datalen<5000
ret=recv(...)
datalen+=ret
....
因為recv這樣的特性,所以你並不能保證每次recv收到的數據包是一個完整的, 它可能包含了伺服器一次發送數據包的一部分,也可能包括了伺服器先後幾次發送的幾個數據包。因此,你必須自己設計傳輸協議,能夠明確的分辨伺服器發送過來的每個數據包(比如每個數據包都有一個明顯的結尾,或者數據包頭加上數據包的長度)
Ⅶ socket編程在windows和linux下的區別
下面大概分幾個方面進行羅列:
Linux要包含
[cpp]
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <arpa/inet.h>
等頭文件,而windows下則是包含
[cpp]
#include <winsock.h>
。
Linux中socket為整形,Windows中為一個SOCKET。
Linux中關閉socket為close,Windows中為closesocket。
Linux中有變數socklen_t,Windows中直接為int。
因為linux中的socket與普通的fd一樣,所以可以在TCP的socket中,發送與接收數據時,直接使用read和write。而windows只能使用recv和send。
設置socet選項,比如設置socket為非阻塞的。Linux下為
[cpp]
flag = fcntl (fd, F_GETFL);
fcntl (fd, F_SETFL, flag | O_NONBLOCK);
,Windows下為
[cpp]
flag = 1;
ioctlsocket (fd, FIONBIO, (unsigned long *) &flag);
。
當非阻塞socket的TCP連接正在進行時,Linux的錯誤號為EINPROGRESS,Windows的錯誤號為WSAEWOULDBLOCK。
file
Linux下面,文件換行是"\n",而windows下面是"\r\n"。
Linux下面,目錄分隔符是"/",而windows下面是"\"。
Linux與Windows下面,均可以使用stat調用來查詢文件信息。但是,Linux只支持2G大小,而Windows只支持4G大小。為了支持更大的文件查詢,可以在Linux環境下加
_FILE_OFFSET_BITS=64定義,在Windows下面使用_stat64調用,入參為struct __stat64。
Linux中可根據stat的st_mode判斷文件類型,有S_ISREG、S_ISDIR等宏。Windows中沒有,需要自己定義相應的宏,如
[cpp]
#define S_ISREG(m) (((m) & 0170000) == (0100000))
#define S_ISDIR(m) (((m) & 0170000) == (0040000))
Linux中刪除文件是unlink,Windows中為DeleteFile。
time
Linux中,time_t結構是長整形。而windows中,time_t結構是64位的整形。如果要在windows始time_t為32位無符號整形,可以加宏定義,_USE_32BIT_TIME_T。
Linux中,sleep的單位為秒。Windows中,Sleep的單位為毫秒。即,Linux下sleep (1),在Windows環境下則需要Sleep (1000)。
Windows中的timecmp宏,不支持大於等於或者小於等於。
Windows中沒有struct timeval結構的加減宏可以使用,需要手動定義:
[cpp]
#define MICROSECONDS (1000 * 1000)
#define timeradd(t1, t2, t3) do { \
(t3)->tv_sec = (t1)->tv_sec + (t2)->tv_sec; \
(t3)->tv_usec = (t1)->tv_usec + (t2)->tv_usec % MICROSECONDS; \
if ((t1)->tv_usec + (t2)->tv_usec > MICROSECONDS) (t3)->tv_sec ++; \
} while (0)
#define timersub(t1, t2, t3) do { \
(t3)->tv_sec = (t1)->tv_sec - (t2)->tv_sec; \
(t3)->tv_usec = (t1)->tv_usec - (t2)->tv_usec; \
if ((t1)->tv_usec - (t2)->tv_usec < 0) (t3)->tv_usec --, (t3)->tv_usec += MICROSECONDS; \
} while (0)
調用進程
Linux下可以直接使用system來調用外部程序。Windows最好使用WinExec,因為WinExec可以支持是打開還是隱藏程序窗口。用WinExec的第二個入參指明,如
SW_SHOW/SW_HIDE。
雜項
Linux為srandom和random函數,Windows為srand和rand函數。
Linux為snprintf,Windows為_snprintf。
同理,Linux中的strcasecmp,Windows為_stricmp。
錯誤處理
Linux下面,通常使用全局變數errno來表示函數執行的錯誤號。Windows下要使用GetLastError ()調用來取得。
Linux環境下僅有的
這些函數或者宏,Windows中完全沒有,需要用戶手動實現。
atoll
[cpp]
long long
atoll (const char *p)
{
int minus = 0;
long long value = 0;
if (*p == '-')
{
minus ++;
p ++;
}
while (*p >= '0' && *p <= '9')
{
value *= 10;
value += *p - '0';
p ++;
}
return minus ? 0 - value : value;
}
gettimeofday
[cpp]
#if defined(_MSC_VER) || defined(_MSC_EXTENSIONS)
#define EPOCHFILETIME 11644473600000000Ui64
#else
#define EPOCHFILETIME 11644473600000000ULL
#endif
struct timezone
{
int tz_minuteswest;
int tz_dsttime;
};
int
gettimeofday (struct timeval *tv, struct timezone *tz)
{
FILETIME ft;
LARGE_INTEGER li;
__int64 t;
static int tzflag;
if (tv)
{
GetSystemTimeAsFileTime (&ft);
li.LowPart = ft.dwLowDateTime;
li.HighPart = ft.dwHighDateTime;
t = li.QuadPart; /* In 100-nanosecond intervals */
t -= EPOCHFILETIME; /* Offset to the Epoch time */
t /= 10; /* In microseconds */
tv->tv_sec = (long) (t / 1000000);
tv->tv_usec = (long) (t % 1000000);
}
if (tz)
{
if (!tzflag)
{
_tzset ();
tzflag++;
}
tz->tz_minuteswest = _timezone / 60;
tz->tz_dsttime = _daylight;
}
return 0;
}
編譯相關
當前函數,Linux用__FUNCTION__表示,Windows用__func__表示。
--------------------------------------------------------------------------------
Socket 編程 windows到Linux代碼移植遇到的問題
1)頭文件
windows下winsock.h/winsock2.h
linux下sys/socket.h
錯誤處理:errno.h
2)初始化
windows下需要用WSAStartup
linux下不需要
3)關閉socket
windows下closesocket(...)
linux下close(...)
4)類型
windows下SOCKET
linux下int
如我用到的一些宏:
#ifdef WIN32
typedef int socklen_t;
typedef int ssize_t;
#endif
#ifdef __LINUX__
typedef int SOCKET;
typedef unsigned char BYTE;
typedef unsigned long DWORD;
#define FALSE 0
#define SOCKET_ERROR (-1)
#endif
5)獲取錯誤碼
windows下getlasterror()/WSAGetLastError()
linux下errno變數
6)設置非阻塞
windows下ioctlsocket()
linux下fcntl() <fcntl.h>
7)send函數最後一個參數
windows下一般設置為0
linux下最好設置為MSG_NOSIGNAL,如果不設置,在發送出錯後有可 能會導致程序退出。
8)毫秒級時間獲取
windows下GetTickCount()
linux下gettimeofday()
3、多線程
多線程: (win)process.h --〉(linux)pthread.h
_beginthread --> pthread_create
_endthread --> pthread_exit
-----------------------------------------------------------------
windows與linux平台使用的socket均繼承自Berkeley socket(rfc3493),他們都支持select I/O模型,均支持使用getaddrinfo與getnameinfo實現協議無關編程。但存在細微差別,
主要有:
頭文件及類庫。windows使用winsock2.h(需要在windows.h前包含),並要鏈接庫ws2_32.lib;linux使用netinet/in.h, netdb.h等。
windows下在使用socket之前與之後要分別使用WSAStartup與WSAClean。
關閉socket,windows使用closesocket,linux使用close。
send*與recv*函數參數之socket長度的類型,windows為int,linux為socklen_t,可預編譯指令中處理這一差異,當平台為windows時#define socklen_t unsigned int。
select函數第一個參數,windows忽略該參數,linux下該參數表示集合中socket的上限值,一般設為sockfd(需select的socket) + 1。
windows下socket函數返回值類型為SOCKET(unsigned int),其中發生錯誤時返回INVALID_SOCKET(0),linux下socket函數返回值類型int, 發生錯誤時返回-1。
另外,如果綁定本機回環地址,windows下sendto函數可以通過,linux下sendto回報錯:errno=22, Invalid arguement。一般情況下均綁定通配地址。
轉載jlins
Ⅷ linux手冊翻譯——socket(2)
socket - 創建一個用於通信的端點
socket() 創建用於通信的端點並返回引用該端點的文件描述符。 成功調用時返回的文件描述符,將是當前沒有被進程打開的所有文件描述符中編號最低的。
domain 參數指定一個通信域; 以決定用於通信的協議族。 這些系列在 <sys/socket.h> 中定義。 目前 Linux 內核理解的格式包括:
當然最常用的當然是 AF_INET ,即IPV4。
上述地址族的更多詳細信息以及其他幾個地址族的信息可以在 address_families(7) 中找到。
套接字具有指定的 type ,它指定了通信語義。 當前定義的類型有:
某些套接字類型可能不會被所有協議族實現。
從 Linux 2.6.27 開始,type 參數有第二個用途:除了指定套接字類型之外,它還可以包含以下任何值的按位或,以修改 socket() 的行為:
老朋友了,上述兩個,第一個是非阻塞,第二個是執行exec時自動關閉。
protocol 指定要與套接字一起使用的特定協議。 通常只存在一個協議來支持給定協議族中的特定套接字類型 ,在這種情況下,protocol 可以指定為 0。但是,可能存在許多協議,在這種情況下,必須在此指定特定協議方式。 特定協議對應的編號可以查看文件: /etc/protocols
SOCK_STREAM 類型的套接字是全雙工位元組流。 它們不保留記錄邊界。 流套接字必須處於連接狀態,然後才能在其上發送或接收任何數據。 到另一個套接字的連接是通過 connect(2) 調用創建的。 連接後,可以使用 read(2) 和 write(2) 調用或 其變體send(2) 和 recv(2) 的來傳輸數據。 當會話完成時,可以執行 close(2)。 帶外數據也可以按照 send(2) 中的描述進行傳輸,並按照 recv(2) 中的描述進行接收。
實現 SOCK_STREAM 的通信協議確保數據不會丟失或重復。 如果協議的緩沖空間中存在一條數據在合理的時間內不能成功傳輸,則認為該連接已失效。 當 SO_KEEPALIVE 在套接字上啟用時,將會以特定於協議的方式檢查另一端是否仍然存在。 如果進程在損壞的流上發送或接收,則會引發 SIGPIPE 信號; 這會導致不處理信號的進程退出。 SOCK_SEQPACKET 套接字使用與 SOCK_STREAM 套接字相同的系統調用。 唯一的區別是 read(2) 調用將只返回請求的數據量,到達數據包中剩餘的其他數據都將被丟棄。 傳入數據報中的所有消息邊界也被保留。
SOCK_DGRAM 和 SOCK_RAW 套接字允許將數據報發送到在 sendto(2) 調用中指定的通信者。 數據報通常用 recvfrom(2) 接收,它返回下一個數據報及其發送者的地址。
SOCK_PACKET 是一種過時的套接字類型,用於直接從設備驅動程序接收原始數據包。 改用 packet(7)。
An fcntl(2) F_SETOWN operation can be used to specify a process or process group to receive a SIGURG signal when the out-of-band data arrives or SIGPIPE signal when a SOCK_STREAM connection breaks unexpectedly. This operation may also be used to set the process or process group that receives the I/O and asynchronous notification of I/O events via SIGIO. Using F_SETOWN is equivalent to an ioctl(2) call with the FIOSETOWN or SIOCSPGRP argument.
When the network signals an error condition to the protocol mole (e.g., using an ICMP message for IP) the pending error flag is set for the socket. The next operation on this socket will return the error code of the pending error. For some protocols it is possible to enable a per-socket error queue to retrieve detailed information about the error; see IP_RECVERR in ip(7).
套接字的操作由套接字選項控制。 這些選項在 <sys/socket.h> 中定義。 函數setsockopt(2) 和getsockopt(2) 用於設置和獲取選項。對於選項的描述,詳見socket(7).
成功時,將返回新套接字的文件描述符。 出錯時,返回 -1,並設置 errno 以指示錯誤。
POSIX.1-2001, POSIX.1-2008, 4.4BSD.
The SOCK_NONBLOCK and SOCK_CLOEXEC flags are Linux-specific.
socket() appeared in 4.2BSD. It is generally portable to/from non-BSD systems supporting clones of the BSD socket layer (including System V variants).
在 4.x BSD 下用於協議族的清單常量是 PF_UNIX、PF_INET 等,而 AF_UNIX、AF_INET 等用於地址族。 但是,BSD 手冊頁已經承諾:「協議族通常與地址族相同」,隨後的標准到處都使用 AF_*。
Ⅸ linux socket返回的int值是什麼 文件描述符一樣的東西嗎
對,socket成功建立後,返回值是一個特殊的文件描述符。這個描述符對應的不是物理文件,而是一個socket。
當初,unix在加入socket功能時,將網路傳輸功能與文件的讀寫,當做相同的邏輯操作。相應地,將打開socket的返回值,與打開文件的返回值當做邏輯相同的描述符
Ⅹ linux socket阻塞recv怎麼返回
recv是socket編程中最常用的函數之一,在阻塞狀態的recv有時候會返回不同的值,而對於錯誤值也有相應的錯誤碼,分別對應不同的狀態,下面是我針對常見的幾種網路狀態的簡單總結。
首先阻塞接收的recv有時候會返回0,這僅在對端已經關閉TCP連接時才會發生。
而當拔掉設備網線的時候,recv並不會發生變化,仍然阻塞,如果在這個拔網線階段,socket被關掉了,後果可能就是recv永久的阻塞了。
所以一般對於阻塞的socket都會用setsockopt來設置recv超時。
當超時時間到達後,recv會返回錯誤,也就是-1,而此時的錯誤碼是EAGAIN或者EWOULDBLOCK,POSIX.1-2001上允許兩個任意一個出現都行,所以建議在判斷錯誤碼上兩個都寫上。
如果socket是被對方用linger為0的形式關掉,也就是直接發RST的方式關閉的時候,recv也會返回錯誤,錯誤碼是ENOENT
還有一種經常在代碼中常見的錯誤碼,那就是EINTER,意思是系統在接收的時候因為收到其他中斷信號而被迫返回,不算socket故障,應該繼續接收。但是這種情況非常難再現,我嘗試過一邊一直在不停的發信號,一邊用recv接收數據,也沒有出現過。這種異常錯誤我附近只有一個朋友在用write的時候見到過一次,但是總是會有概率出現的,所以作為完善的程序必須對此錯誤進行特殊處理。
一般設置超時的阻塞recv常用的方法都如下:
while(1)
{
cnt = (int)recv(m_socket, pBuf,RECVSIZE, 0);
if( cnt >0 )
{
//正常處理數據
}
else
{
if((cnt<0) &&(errno == EAGAIN||errno == EWOULDBLOCK||errno == EINTR)) //這幾種錯誤碼,認為連接是正常的,繼續接收
{
continue;//繼續接收數據
}
break;//跳出接收循環
}
}
阻塞與非阻塞recv返回值沒有區分,都是 <0 出錯 =0 連接關閉 >0 接收到數據大小。
Linux環境下,須如下定義:struct timeval timeout = {3,0};
//設置發送超時
setsockopt(socket,SOL_SOCKET,SO_SNDTIMEO,(char *)&timeout,sizeof(struct timeval));
//設置接收超時
setsockopt(socket,SOL_SOCKET,SO_RCVTIMEO,(char *)&timeout,sizeof(struct timeval));