成功大學多媒體行動實驗室 有做出以下的產品耶 SCTP-MOVIDEO Server
要使用sctp必需先安裝sctp套件$ sudo apt-get install libsctp-dev
在寫一個簡單的sctp的server-client出現以下錯誤
ren@notebook:~/svn/renyang-learn/socket/sctp/ftp/test$ gcc -c copy_clinet.c -o copy_clinet.o
In file included from copy_clinet.c:7:
/usr/include/netinet/in.h:84: 錯誤: expected identifier before numeric constant
找了很久,測了很久,才發現header file的擺放順序有問題!!?
若是下面順序的話,就會出現以上錯誤!#include <sys/socket.h>
#include <netinet/sctp.h>
#include <netinet/in.h>
而以下就可以過#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/sctp.h>
這真是太神奇啦~
在編譯serv.c時會出現以下錯誤
ren@notebook:~/Desktop/homework$ gcc serv.c -o serv
/tmp/ccwbUY4s.o: In function `main':
serv.c:(.text+0x1eb): undefined reference to `sctp_sendmsg'
collect2: ld returned 1 exit status
解決方法:多加一個 -lsctp 的參數ren@notebook:~/Desktop/homework$ gcc serv.c -lsctp -o serv
gcc -Wall -O2 -c client.c -o client.o
client.c: In function 'main':
client.c:33: warning: implicit declaration of function 'inet_pton'
client.c:38: warning: implicit declaration of function 'close'
表示inet_pton與close函式的header file沒有正確的被include進來
分別要include arpa/inet.h和unistd.h
ren@notebook:~/svn/renyang-learn/socket/sctp/ftp$ make
gcc -c client.c -o client.o
In file included from client.c:4:
/usr/include/netinet/in.h:84: 錯誤: expected identifier before numeric constant
make: *** [client.o] Error 1
表示有重覆include in.h之類的
inet_pton函數:將點分十進位串轉換成網路位元組序二進位值,此函數對IPv4位址和IPv6位址都能處理。
#include <arpa/inet.h>
int inet_pton(int family,const char * strptr,void * addrptr);
返回:1---成功 0---輸入不是有效的表達格式 -1---失敗
strtol(將字符串轉換成長整型數)
表頭文件:#include <stdlib.h>
定義函數:long int strtol(const char *nptr,char **endptr,int base);
函數說明:strtol()會將參數nptr字符串根據參數base來轉換成長整型數。參數base範圍從2至36,或0。參數base代表採用的進制方式,如 base值為10則採用10進制,若base值為16則採用16進制等。當base值為0時則是採用10進制做轉換,但遇到如'0x'前置字符則會使用 16進制做轉換。一開始strtol()會掃描參數nptr字符串,跳過前面的空格字符,直到遇上數字或正負符號才開始做轉換,再遇到非數字或字符串結束時('\0')結束轉換,並將結果返回。若參數endptr不為NULL,則會將遇到不合條件而終止的nptr中的字符指針由endptr返回。
返回值:返回轉換後的長整型數,否則返回ERANGE並將錯誤代碼存入errno中。
附加說明:ERANGE指定的轉換字符串超出合法範圍。
參考網站
參考資料:
SCTP Programmer's Guide
Stream Control Transmission Protocol (SCTP)
IBM SCTP socket API
SCTP Programmer's Guide: HP
以IPv6有線/無線網路Multihome-based SCTP通訊協定實作之可切換式多媒體視訊串流平台
一些sctp的文章
我國IPv6建置發展計畫
The Stream Control Transmission Protocol(SCTP) Research and simulation Page
程式資料
Linux C編程---網路編程
SCTP相關網站:
傳輸層:TCP、UDP 和 SCTP
lksctp Project
Quick HOWTO : Ch15 : Linux FTP Server Setup
使用 SCTP 優化網路
Linux Kernel SCTP
Stream Control Transmission Protocol
Solaris(TM) Stream Control Transmission Protocol (SCTP)
Better networking with SCTP
SCTP Features
2009年2月5日 星期四
socket - sctp
2009年2月4日 星期三
socket - tcp - 觀念
程式寫出來了,觀念還是要說一下,tcp實作檔案傳輸請到這裡
IPv4的定義:
struct in_addr {
in_addr_t s_addr;
};
struct sockaddr_in{
unit8_t sin_len;
sa_family_t sin_family;
in_port_t sin_port;
struct in_addr sin_addr;
char sin_zero[8];
};
一般在使用socket通訊時,分身為server的應用程式必需先建立一個通訊端(socket)
再以bind系統呼叫(system call)來完成通訊端的命名
server的應用程式會以listen系統呼叫來建立一個佇列(queue)
再以accept系統呼叫來進行接收
建立好連線之後,通訊端可看做是一個低階的檔案描述子(file descriptor)程式,只要利用read及write指令即可完成雙向的資料通訊
Socket提供了兩種通訊型式
–AF_UNIX
•主要是用來讓單一台電腦內的兩個應用程式,利用標準(或非標準)裝置的埠(PORT)來做資料的傳輸
。
–AF_INET
•基本的Internet Protocol(IP)的通訊協定,其又可分為stream與datagram等兩層的服務
–Stream是一種可靠的雙向通訊方式,可確保資料的完整性
–Datagram是一種不需要建立連結的通訊方式,無法保證所傳送出資料的完整性
在Linux和Windows網絡編程時需要用到htons和htonl函數,用來將主機字節順序轉換為網絡字節順序。
得到的結果是4096,一開始看感覺很怪。
解釋如下,數字16的16進製表示為0x0010,數字4096的16進製表示為0x1000。由於Intel機器是little-end,存儲數字16時實際順序為1000,存儲4096時實際順序為0010。因此在發送網絡包時為了報文中數據為0010,需要經過htons進行字節轉換。如果用IBM等big-end機器,則沒有這種字節順序轉換,但為了程序的可移植性,也最好用這個函數。
另外用注意,數字所佔位數小於或等於一個byte(8 bits)時,不要用htons轉換。這是因為對於主機來說,big-end and little-end的最小單位為字節(byte)。
sin_family指代協議族,在socket編程中只能是AF_INET
sin_port存儲端口號(使用網絡字節順序)
sin_addr存儲IP地址,使用in_addr這個數據結構
sin_zero是為了讓sockaddr與sockaddr_in兩個數據結構保持大小相同而保留的空字節。
s_addr按照網絡字節順序存儲IP地址
sockaddr_in和sockaddr是並列的結構,指向sockaddr_in的結構體的指針也可以指向
sockadd的結構體,並代替它。也就是說,你可以使用sockaddr_in建立你所需要的信息,
在最後用進行類型轉換就可以了bzero((char*)&mysock,sizeof(mysock));//初始化
mysock結構體名
mysock.sa_family=AF_INET;
mysock.sin_addr.s_addr=inet_addr("192.168.0.1");
……
等到要做轉換的時候用:
(struct sockaddr*)mysock
換句話說在設定的時候用sockaddr_in
而在使用的時候用sockaddr
其實sockaddr_in與sockaddr是一樣的東西
我想是因為要相容於之後的版本,所以,在設定的時候用不同的sockaddr_in
而真正在使用的時候,均使用sockaddr,也就是要轉換成sockaddr的指標
詳細資料可以參考我寫的tcp程式碼,我有註釋在裡面!
[2009.04.30 補充]
在同一個ip,應用程式不可以bind同一個port,但是,透過
setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &flag, len);
可以決解目前這一個問題,詳情請看
socket編程:SO_REUSEADDR例解 (轉)
參考資料:
結構體sockaddr_in和sockaddr用法的問題
TCP 與 UDP
複製檔案 - fread fwrite
請問int a=send(socket,buf,len,flags) 這個a是代表發送的包的大小嗎?(各個參數值已知的情況下)
return與exit的區別
exit是結束一個程序,它將刪除程序使用的記憶體空間,同時把錯誤訊息回傳給父程序,在父程序中wait系統呼叫將接受到此返回訊息。
例子:void a()
{
exit();
}
void main()
{
while(1)
{
a();
}
}
這個程序並不會死循環,因為在a函數中調用exit,所以整個程序就結束了。但如果你在a函數中使用return,那麼就是個死循環了。
例子2:#include <iostream.h>
using namespace std;
class bbb
{
public:
bbb();
~bbb();
};
bbb::bbb()
{
// do nothing
}
bbb::~bbb()
{
cout << "destruct" << endl;;
}
main()
{
bbb b;
//exit(0);
return 0;
}
然後把//exit(0)的註釋去掉再編譯運行一次。會有不同的結果。
答:當沒有exit(0)時,return 0時,系統會輸出並清理緩衝區並關閉標準輸入cin、標準輸出cout、標準錯誤cerr、標準日誌clog。
當有exit(0)時,c函數會輸出並清理stdin, stdout,現在stdout已經被關閉了,在執行return 0時,cout的緩衝區的數據已經沒有寫入的目標了,所以無輸出。
這只能說明cout和stdout, cin 和stdin用的是不同的緩衝區。
參考資料:
return與exit的區別是什麼?
return和exit的區別
解決ubuntu的解析度
這次回家,
在家裡那一台爛電腦灌ubuntu 8.04,
一開始沒有問題,但是,更新完驅動程式,哭哭~看不到螢幕~
因為螢幕太爛,
找了一堆解決方式,最後,有解決~
不過,我忘記用哪一個方法解決了,下次再回家查好了~
參考資料:
ubuntu 螢幕解析度及 flash 問題解決
ubuntu - 寬螢幕解析度設定
解決ubuntu登入畫面解析度錯誤
2009年2月3日 星期二
I/O - STDIN_FILENO
STDIN_FILENO 是标准输入的文件描述符
详见/usr/include/unistd.h
代码:
/* Standard file descriptors. */
#define STDIN_FILENO 0 /* Standard input. */
#define STDOUT_FILENO 1 /* Standard output. */
#define STDERR_FILENO 2 /* Standard error output. */
例:
int read(STDIN_FILENO, char *buffer, int sizeof(buffer));
例:
stdin
是讓使用者輸入字串,且回傳的是FILE的指標
參考資料:
STDIN和STDIN_FILENO的區別
file and stream : stdin and STDIN_FILENO
read function 設定Non-Blocking I/O的方式
socket - udp
以下有一個簡單的透過UDP來傳送訊息的程式,udp與tcp的差別在於tcp不能由server連續傳訊息給client而必需client-server-client間接傳。
而udp就可以由server連續傳訊息給client
udpserver.c
//==============================include file==========================
#include <sys/types.h>
#include <sys/socket.h>
#include <string.h>
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
//====================================================================
//==============================define variable=======================
#define MAXLINE 80
#define SERV_PORT 8888
//====================================================================
//==============================define function=======================
void do_echo(int sockfd,struct sockaddr *pcliaddr,socklen_t clilen);
//====================================================================
//=============================main function==========================
int main(int argc,char *argv[])
{
int sockfd;
struct sockaddr_in servaddr,cliaddr;
// create a socket, using the UDP
sockfd = socket(AF_INET,SOCK_DGRAM,0);
// init servaddr
memset(&servaddr,0,sizeof(servaddr));
servaddr.sin_family=AF_INET;
servaddr.sin_addr.s_addr=INADDR_ANY;
servaddr.sin_port=htons(SERV_PORT);
// bind address and port to socket
if (bind(sockfd,(struct sockaddr *)&servaddr,sizeof(servaddr))==-1)
{
perror("bind error,the ip address is wrong");
exit(1);
}
do_echo(sockfd,(struct sockaddr*)&cliaddr,sizeof(cliaddr));
return 0;
}
//====================================================================
//==============================function implement====================
void do_echo(int sockfd,struct sockaddr *pcliaddr,socklen_t clilen)
{
int n;
socklen_t len;
char mesg[MAXLINE];
for (;;)
{
len=clilen;
// wait for receive data
n = recvfrom(sockfd,mesg,MAXLINE,0,pcliaddr,&len);
// sent data back to client
sendto(sockfd,mesg,n,0,pcliaddr,len);
}
}
//====================================================================
udpclient.c
//=============================include file================================
#include <sys/types.h>
#include <sys/socket.h>
#include <string.h>
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include <arpa/inet.h>
#include <unistd.h>
//=========================================================================
//=============================define variable=============================
#define MAXLINE 80
#define SERV_PORT 8888
//=========================================================================
//=============================define function=============================
void do_cli(FILE *fp,int sockfd,struct sockaddr *pservaddr,socklen_t servlen);
//=========================================================================
//=============================main function===============================
int main(int argc,char *argv[])
{
int sockfd;
struct sockaddr_in servaddr;
char error_message[20];
// check args
if (argc!=2)
{
printf("usage:udpclient <IP address>\n");
exit(1);
}
// init servaddr
memset(&servaddr,0,sizeof(servaddr));
servaddr.sin_family=AF_INET;
servaddr.sin_port=htons(SERV_PORT);
if(inet_pton(AF_INET,argv[1],&servaddr.sin_addr)<=0)
{
sprintf(error_message,"[%s] is not a valid IP address\n",argv[1]);
fputs(error_message,stderr);
exit(1);
}
// build the socket, using the UDP
sockfd=socket(AF_INET,SOCK_DGRAM,0);
do_cli(stdin,sockfd,(struct sockaddr*)&servaddr,sizeof(servaddr));
return 0;
}
//=========================================================================
//=============================function implement==========================
void do_cli(FILE *fp,int sockfd,struct sockaddr *pservaddr,socklen_t servlen)
{
int n;
char sendline[MAXLINE],recvline[MAXLINE+1];
// connect to server
if (connect(sockfd,pservaddr,servlen)==-1)
{
perror("connect error");
exit(1);
}
while (fgets(sendline,MAXLINE,fp)!=NULL)
{
// read a line and send to server
write(sockfd,sendline,strlen(sendline));
// receive data from server
n=read(sockfd,recvline,MAXLINE);
if (n==-1)
{
perror("read error");
exit(1);
}
// terminate string
// 依字串的最後面加上一個結束符號
recvline[n]=0;
fputs(recvline,stdout);
}
}
//=========================================================================
有用到的新的東西:
void * memset ( void * ptr, int value, size_t num );
把ptr指標指到的地方,用value的值填滿num個
參考
host to network short
uint16_t htons(uint16_t hostshort);
htons函數用來轉換u_short了來自主機的TCP / IP網絡字節順序(即big-endian )的.
參數hostshort [ ] 16位元數的主機字節順序.
返回值的htons函數返回值的TCP / IP網路字元順序.
須知htons函數有一個16位號碼主機字元順序並返回一個16位數字網路字元
參考
參考2
參考3
htons-htons的功能
FILE * stdin
等待使用者輸入字串,並回傳FILE的指標,與scanf比起來,scanf會以「空白」當作分隔
但是,透過char * fgets ( char * str, int num, stdin );
會把使用者輸入的字串存放到str的指標中,且長度必需小於num-1,如此一來不會以「空白」當作中斷
當我們輸入"good"時,實際上存到str的會是"good\n",也就是在最後面加上一個結束符號。
這裡要注意的是它自動加入的是null
A null character is automatically appended in str after the characters read to signal the end of the C string.
但是非常奇怪的就是用strlen(str)會比原來的長度還要加1,所以,我猜測最後加入的不是'\0'而是'\n',所以,長度才會比原本的多一
這裡就要提到,若使用char *gets( char *str )
不會在最後加入一個結束符號。
FILE *stdout
可以把字串傳送到螢幕上
透過int fputs ( const char * str, stdout);
可以把str指標指到的字串送到螢幕上
FILE *stderr
可以把字串送到錯誤串流
透過int fputs(const char *str,stderr);
可以把str指標指到的字串送到螢幕上
void perror ( const char * str );
perror()用來將上一個函數發生錯誤的原因輸出到標準錯誤(stderr)。參數s所指的字串會先印出,後面再加上錯誤原因字串。此錯誤原因依照全局變量errno的值來決定要輸出的字符串。
若上一個函數沒有執行失敗的話,那就會出現
"訊息":SUCCESS
參考
參考2
參考3
參考4
參考5
上面的一些函數後面都不能加變數,因此可能必需與
int sprintf ( char * str, const char * format, ... );
一起使用。先把所有的變數一起轉成字串,再把字串傳給上面幾個函數使用
參考
int fprintf ( FILE * stream, const char * format, ... );
把字串輸入到檔案中
fprintf(stderr,"there are some errors:%s",string);
回傳值是寫入多少字元
參考資料:
recvfrom
練習 Socket UDP 通訊實驗
socket編程原理
STDIN
編寫Linux下的UDP Client/Server程序
socket - tcp
當client與server連接之後,
client可以連續傳訊息給server,
但是,server不能連續傳訊息給client,
像是server要傳檔案給client,分割好幾份,
則在server傳給client每一份之間,client必需傳一個訊息給server,
如此一來,server才可以傳下一份分割給client
下面我用gcc寫了一個非常簡單的傳輸檔案的程式:
server.c
//==========================include file==================================
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
//========================================================================
//==========================define variable===============================
#define PORT 9734
#define FILEBUFFERSIZE 1024
//========================================================================
//==========================global variable===============================
//========================================================================
//==========================function phototypes===========================
//========================================================================
int main(int argc,char *argv[])
{
int listenfd,connfd;
// 在c語言中,要用到struct時,前面必需要加上struct,在c++中則不需要
struct sockaddr_in server_address;
struct sockaddr_in client_address;
int server_len,client_len;
char temp[FILEBUFFERSIZE];
int ReadByte,WriteByte;
char end[]="#end#"; // 用來判斷是否傳送檔案結束
FILE *fp;
if (argc!=2) {
printf("Insrtuction error!!\n");
printf("./server 'file'\n");
exit(1);
}
if ((fp=fopen(argv[1],"rb"))==NULL) {
fputs("open file error\n",stderr);
exit(1);
}
// divide - test
while((ReadByte=fread(temp,sizeof(char),FILEBUFFERSIZE,fp))>0) {
printf("%d\n",ReadByte);
memset(temp,0,FILEBUFFERSIZE);
}
// divide - test
// 1.建立一個新的通訊端:socket(int domain,int type,int protocol),並回傳參數值
listenfd = socket(AF_INET, SOCK_STREAM, 0);
// 2.1.設定為Unix network socket,表示可以在兩個不同的電腦之間傳資料
server_address.sin_family = AF_INET;
// 2.2.server的ip位址,這裡必需是server的ip位址
// inet_addr(), this function translate IP address into specified format for socket
server_address.sin_addr.s_addr=INADDR_ANY;
// server_address.sin_port = 9734;
// 2.3.轉換成little-end,因為intel是little-end
server_address.sin_port = htons(PORT);
// 記錄server端的設定(port,ip,sin_family...)的資料長度
server_len = sizeof(server_address);
// 3.Socket 出入口需Binding到TCP address
if(bind(listenfd,(struct sockaddr*) &server_address, server_len)==-1){
printf("bind error");
exit(1);
}
// 4.建立一個queue以接收其他程式所送達的連線要求,queue的大小為5
if (listen(listenfd,5)==-1){
printf("listening error");
exit(1);
}
// 當產生了一個佇列(queue)後,再來就是要把queue中的連結請求(Connect Request)讀出
while(1)
{
// temp存放要傳送的檔案
char temp[FILEBUFFERSIZE];
printf("server waiting \n");
client_len = sizeof(client_address); // 了解client的設定資料結構長度
// 5.以accept指令來等待client端送去連線要求(connect request)
// 由client_address獲得client端的網路位置
// connfd即由新的connected socket 所存放參數的地方。用來和client 進行資料輸出入
connfd = accept(listenfd,(struct sockaddr *)&client_address, &client_len);
if (connfd==-1){
printf("Error:accept()\n");
exit(1);
}
// 由connfd讀取資料存到temp的位址中,buffer大小為1024 bytes
read(connfd, &temp, FILEBUFFERSIZE);
if (printf("ch : %s \n",temp)==-1){
printf("Read error!\n");
exit(1);
}
else
{
if (strncmp(temp,"get",strlen("get"))==0)
{
printf("File transmite...\n");
fp=fopen(argv[1],"rb");
if (fp==NULL) {
printf("open file error!!\n");
exit(1);
}
memset(temp,0,sizeof(temp));
ReadByte=fread(temp,sizeof(char),FILEBUFFERSIZE,fp);
while(ReadByte>0){
printf("read %d Byte\n",ReadByte);
WriteByte=write(connfd,temp,ReadByte);
printf("transmite %d bytes\n",WriteByte);
memset(temp,0,sizeof(temp));
ReadByte=read(connfd,temp,FILEBUFFERSIZE);
printf("%s\n",temp);
memset(temp,0,FILEBUFFERSIZE);
ReadByte=fread(temp,sizeof(char),FILEBUFFERSIZE,fp);
}
}
WriteByte=write(connfd,end,sizeof(end));
printf("Transmite %d bytes\n",WriteByte);
}
// 關掉connected socket
close(connfd);
}
// 關掉listen的socket
close(listenfd);
fclose(fp);
return 0;
}
//==========================function implementation=======================
//========================================================================
client.c
//============================include file===================================
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
//===========================================================================
//=============================define variable===============================
#define PORT 9734
#define FILEBUFFERSIZE 1024
//===========================================================================
int main(int argc,char *argv[])
{
int sockfd;
int ReadByte;
struct sockaddr_in address;
int client_len,result;
FILE *fp;
char server_addr[15];
if (argc!=2) {
fputs("./client get",stderr);
exit(1);
}
if((fp=fopen("copy","wb"))==NULL) {
printf("create error\n");
exit(1);
}
fclose(fp);
printf("Please input server's ip:");
scanf("%s",server_addr);
// 建立一個socket
sockfd = socket(AF_INET, SOCK_STREAM, 0); address.sin_family = AF_INET;
// 以下存放的必需是server的ip位址
address.sin_addr.s_addr=inet_addr(server_addr);
address.sin_port = htons(PORT);
client_len = sizeof(address);
// Client端則呼叫connect()功能,要求與Server主機建立連接通道
result = connect(sockfd, (struct sockaddr *)&address,client_len);
if(result == -1) // 若傳回-1則表示連線失敗
{
perror("oops: client1");
fclose(fp);
exit(1) ;
}
// 傳送資料到server端
if (write( sockfd, &(*argv[1]) , FILEBUFFERSIZE)==-1){
printf("write error\n");
fclose(fp);
exit(1);
}
else {
// 接收檔案
char temp[FILEBUFFERSIZE];
memset(temp,0,FILEBUFFERSIZE);
ReadByte=read(sockfd,temp,FILEBUFFERSIZE);
printf("get the %d bytes\n",ReadByte);
fp = fopen("copy","wb");
if (fp==NULL) {
printf("open file error!!\n");
exit(1);
}
else {
while(ReadByte>0) {
if (strncmp(temp,"#end#",strlen("#end#"))==0) {
printf("The connect is over\n");
break;
}
fwrite(temp,sizeof(char),ReadByte,fp);
write(sockfd,"I got\n",sizeof("I got\n"));
memset(temp,0,FILEBUFFERSIZE);
ReadByte=read(sockfd,temp,FILEBUFFERSIZE);
printf("I got the %d bytes\n",ReadByte);
}
fclose(fp);
}
// 當client接收到資料後,必需要write資料到server才能再read資料!,這樣才叫被動啊!!
}
close( sockfd); // 關掉socket介面
return 0;
}
執行:
[user@host ~]$ ./server source
[user@host ~]$ ./client get
就會在目錄下出現一個copy的檔案
這裡用到的新函數
size_t fread ( void * ptr, size_t size, size_t count, FILE * stream );
由FILE指標指到的檔案讀取單位為size byte,且個數上限為count的資料,並存到ptr所指到的指標位址空間,回傳值為實際讀取到的byte數
size_t fwrite ( const void * ptr, size_t size, size_t count, FILE * stream );
由FILE指標指到的檔案寫入單位為size byte,且個數上限為count的資料,並存到ptr所指到的指標位址空間,回傳值為實際寫入到的byte數
int socket(int domain, int type, int protocol)
– Doman : AF_UNIX UNIX files system sockets
AF_INET → UNIX network sockets
AF_ISO → ISO standard protocols
AF_NS → Xerox Network Systems protocols
AF_IPX → Novell IPX protocol
– Type : SOCK_STREAM(TCP),SOCK_DGRAM(UDP)
– Protocol : default 0
int bind(int socket, const struct socket * address, size_t address_len);
socket : return value from socket function
– 利用socket函數產生socket後所回傳的參數值
• *address : struct sockaddr_un, struct sockaddr_in
– 對映於通訊端(socket)所宣告的資料結構
• address_len : address length
– 參數為資料結構的大小
當成功後,函式會傳回0以代表成功,若失敗即傳回-1。
建立一個queue以接收其他程式所送達的連線要求(request)
– int listen(int socket, int backlog)
• socket : return value from socket function
– 為所新建立的socket descriptor
• Backlog : Queue length
– 代表所欲建立的queue大小為多少
當成功後,函式會傳回0以代表成功,若失敗即傳回-1。
當產生了一個佇列(queue)後,再來就是要把queue中的連結請求(Connect Request)讀出
• 其函數的原型如下:
– int connect(int socket, const struct sockaddr
*address, size_t address_len)
• socket : return value from socket function
– 為新建立的socket descriptor
• *address : struct sockaddr_un, struct sockaddr_in
– 對映於通訊端(socket)所宣告的資料結構
• address_len : address length
– 為address資料結構的大小
SOCKET accept(SOCKET s,struct sockaddr* addr,int* addrlen);
s:一個設定為listen狀態的socket
sddr:Client端位址資訊,由函式自動產生填入
addrlen:sddr長度,由函式自動產生
回傳值:-1表示錯誤,否則傳回另一個包含Client端資訊的新socket
descriptor,作為傳送資料用
傳進accept()的listen socket本身並沒有辦法作資料的傳輸,所以必須透過accept()產生一個包含通訊協定、Server、Client資訊的新socket,利用他就可以進行資料的傳輸了
int count=send( int sockfd, char *buffer, int buflen, int flags )
–count:傳送資料的大小
–buffer:資料傳送的指標
–buflen:資料長度
–flag:通常設為0
–return為實際傳送的byte數
–Or write
• int write(int sockfd, char * buffer, int buflen);
Int count=recv( int sockfd, char *buffer, int buflen, int flags )
–Count:接收到的資料大小
–buffer:資料接收後儲存位址的指標
–buflen:資料長度
–flag:通常設為0
–return為實際傳送的byte數
–Or read
• int read(int sockfd, char * buffer, int buflen);
int close (int sockfd) ;
用來關閉socket,並且終止TCP連線
參考資料:
Linux socket 編程入門
網路程式規畫
TCP通訊協定的server程式及client程式
socket編程原理
使用Socket完成FTP檔案存取
程式設計範例及習題 Chapter 5 網路程式範例
Socket Programming HOWTO
以後可能會用到:
[C/C++] 解決Socket連續Bind同一個Port的問題
UNIX Network Programming Source Code