1、socket 網絡套接字linux
建立
函數原型:
int socket(int domain, int type, int protocol);
參數說明:
domain:協議域,又稱協議族(family)。經常使用的協議族有AF_INET、AF_INET六、AF_LOCAL(或稱AF_UNIX,Unix域Socket)、AF_ROUTE等。協議族決定了socket的地址類型,在通訊中必須採用對應的地址,如AF_INET決定了要用ipv4地址(32位的)與端口號(16位的)的組合、AF_UNIX決定了要用一個絕對路徑名做爲地址。
type:指定Socket類型。經常使用的socket類型有SOCK_STREAM、SOCK_DGRAM、SOCK_RAW、SOCK_PACKET、SOCK_SEQPACKET等。流式Socket(SOCK_STREAM)是一種面向鏈接的Socket,針對於面向鏈接的TCP服務應用。數據報式Socket(SOCK_DGRAM)是一種無鏈接的Socket,對應於無鏈接的UDP服務應用。
protocol:指定協議。經常使用協議有IPPROTO_TCP、IPPROTO_UDP、IPPROTO_STCP、IPPROTO_TIPC等,分別對應TCP傳輸協議、UDP傳輸協議、STCP傳輸協議、TIPC傳輸協議。
注意:1.type和protocol不能夠隨意組合,如SOCK_STREAM不能夠跟IPPROTO_UDP組合。當第三個參數爲0時,會自動選擇第二個參數類型對應的默認協議。
2.WindowsSocket下protocol參數中不存在IPPROTO_STCP
2、sockaddr_in
sockaddr_in(在netinet/in.h中定義):
1
2
3
4
5
6
7
8
9
10
11
12
13
struct sockaddr_in
{
short sin_family;/*Address family通常來講AF_INET(地址族)PF_INET(協議族)*/
unsigned short sin_port;/*Port number(必需要採用網絡數據格式,普通數字能夠用htons()函數轉換成網絡數據格式的數字)*/
struct in_addr sin_addr;/*IP address in network byte order(Internet address)*/
unsigned char sin_zero[8];/*Same size as struct sockaddr沒有實際意義,只是爲了 跟SOCKADDR結構在內存中對齊*/
};
in_addr結構
1
2
3
4
5
typedef uint32_t in_addr_t;
struct in_addr
{
in_addr_t s_addr;
};
sin_family指代協議族,在socket編程中只能是AF_INET
sin_port存儲端口號(使用網絡字節順序),在linux下,端口號的範圍0~65535,同時0~1024範圍的端口號已經被系統使用或保留。
sin_addr存儲IP地址,使用in_addr這個數據結構
sin_zero是爲了讓sockaddr與sockaddr_in兩個數據結構保持大小相同而保留的空字節。
s_addr按照網絡字節順序存儲IP地址
3、綁定編程
int bind(SOCKET socket, const struct sockaddr* address, socklen_t address_len);
參數說明:
socket:是一個套接字描述符。
address:是一個sockaddr結構指針,該結構中包含了要結合的地址和端口號。
address_len:肯定address緩衝區的長度。
返回值:
若是函數執行成功,返回值爲0,不然爲SOCKET_ERROR。
4、接收服務器
函數原型:
ssize_t recvfrom(int sockfd, void buf, int len, unsigned int flags, struct socketaddr* from, socket_t* fromlen);
參數說明:
sockfd:標識一個已鏈接套接口的描述字。
buf:接收數據緩衝區。
len:緩衝區長度。
flags:調用操做方式。是如下一個或者多個標誌的組合體,可經過or操做連在一塊兒:
from:(可選)指針,指向裝有源地址的緩衝區。
fromlen:(可選)指針,指向from緩衝區長度值。
5、發送網絡
函數原型:
int sendto( SOCKET s, const char FAR* buf, int size, int flags, const struct sockaddr FAR* to, int tolen);
參數說明:
s:套接字
buf:待發送數據的緩衝區
size:緩衝區長度
flags:調用方式標誌位, 通常爲0, 改變Flags,將會改變Sendto發送的形式
addr:(可選)指針,指向目的套接字的地址
tolen:addr所指地址的長度
返回值:
若是成功,則返回發送的字節數,失敗則返回SOCKET_ERROR。數據結構
服務器端代碼:dom
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>socket
int main(int argc,char *argv[])
{
if(argc!=3)
{
printf("Usage ./server [ip] [port]\n");
return 1;
}
int sock=socket(AF_INET,SOCK_DGRAM,0);
if(sock<0)
{
perror("socket");
return 2;
}函數
struct sockaddr_in local;ui
local.sin_family=AF_INET;//ipv4
local.sin_port=htons(atoi(argv[2]));//主機字節序轉換爲網絡字節序
local.sin_addr.s_addr=inet_addr(argv[1]);//字符串轉in_addr的函數.net
if(bind(sock,(struct sockaddr*)&local,sizeof(local))<0)
{
perror("bind");
return 3;
}
char buf[1024];
struct sockaddr_in client;
while(1)
{
socklen_t len=sizeof(client);
ssize_t s=recvfrom(sock,buf,sizeof(buf)-1,0,(struct sockaddr*)&client,&len);
if(s>0)
{
buf[s]=0;
printf("[%s:%d]:%s\n",inet_ntoa(client.sin_addr),\
ntohs(client.sin_port),buf);
sendto(sock,buf,strlen(buf),0, \
(struct sockaddr*)&client,sizeof(client));
}
}
close(sock);
return 0;
}
客戶端的代碼:
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>
int main(int argc,char *argv[])
{
if(argc!=3)
{
printf("./Usage [ip] [port]\n");
return 1;
}
int sock=socket(AF_INET,SOCK_DGRAM,0);
if(sock<0)
{
perror("socket");
return 2;
}
struct sockaddr_in server;
server.sin_family=AF_INET;
server.sin_port=htons(atoi(argv[2]));
server.sin_addr.s_addr=inet_addr(argv[1]);
char buf[1024];
struct sockaddr_in peer;
while(1)
{
socklen_t len=sizeof(peer);
printf("Please Enter# ");
fflush(stdout);
ssize_t s=read(0,buf,sizeof(buf)-1);
if(s>0)
{
buf[s-1]=0;
sendto(sock,buf,strlen(buf),0,\
(struct sockaddr*)&server,sizeof(server));
ssize_t _s=recvfrom(sock,buf,sizeof(buf)-1,0,\
(struct sockaddr*)&peer,&len);
if(_s>0) { buf[_s]=0; printf("server echo# %s\n",buf); } } } close(sock); return 0; }