Linux socket編程既可以是TCP連接,也可以是UDP連接。Linux socket編程首先要用socket系統調用創建一個套接字,socket系統調用的原型是:
int socket(int domain, int type, int protocol);
當socket函數的type參數指定為SOCK_STREAM時,就相當於建立的是個TCP連接;當type參數指定為SOCK_DGRAM時,建立的就是一個UDP連接。當建立TCP或者UDP連接的時候,注意把第一個參數domain指定為AF_INET。
❷ 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緩沖區大小
進行socket編程有時候可能需要修改下socket的接收緩沖區大小,這里可以使用 setsockopt 函數,但是如果需要修改的緩沖區很大(比如500MB),則還需要修改系統內核的TCP/IP參數,不然接收緩沖區大小會收到內核參數的限制,所以需要改兩個地方。下面以把socket接收緩沖區修改為500MB說明一下要作的修改。《Linux就該這么學》
修改內核TCP/IP參數
在終端用sysctl命令修改socket最大緩沖區限制:
sudo sysctl -w net.core.rmem_max=5242880001
在代碼中用setsockopt函數修改SO_RCVBUF選項
int recvbuff = 500*1024*1024;
if(setsockopt(sockfd, SOL_SOCKET, SO_RCVBUF, (const char*)&recvbuff, sizeof(int)) == -1)
printf("setsocket error
");
else
printf("setsocket success
");12345
以上兩點,只改第1點,一個socket只會預留63個報文的接收緩沖;只改第2點,緩沖區大小會受到rmem_max的限制,如果需要的緩沖區很大的話,必須兩點都改。
❹ 求linux socket網路編程代碼
Linux是多任務的操作系統,可在運行在Intel 80386及更高檔次的PC機、ARMS、MIPS和PowerPC等多種計算機平台,已成為應用廣泛、可靠性高、功能強大的計算機操作系統,Linux具有內核小、效率高、源代碼開放等優點,還內含了TCP/IP網路協議,很適合在伺服器領域使用,而伺服器主要用途之一就是進行網路通信,隨著計算機辦公自動化處理技術的應用與推廣,網路的不斷普及,傳統的紙張式文件傳輸方式已經不再適合發展的需要,人們更期待一種便捷、高效、環保、安全的網路傳輸方式.
協議概述TCP/IP即傳輸控制協議/網路協議[1](Transmission Control Protocol/Internet Protocol),是一個由多種協議組成的協議族,他定義了計算機通過網路互相通信及協議族各層次之間通信的規范,圖1描述了Linux對IP協議族的實現機制[2]。
Linux支持BSD的套接字和全部的TCP/IP協議,是通過網路協議將其視為一組相連的軟體層來實現的,BSD套接字(BSD Socket)由通用的套接字管理軟體支持,該軟體是INET套接字層,用來管理基於IP的TCP與UDP埠到埠的互聯問題,從協議分層來看,IP是網路層協議,TCP是一個可靠的埠到埠的傳輸層協議,他是利用IP層進行傳接報文的,同時也是面向連接的,通過建立一條虛擬電路在不同的網路間傳輸報文,保證所傳輸報文的無丟失性和無重復性。用戶數據報文協議(User Datagram Protocol,UDP)也是利用IP層傳輸報文,但他是一個非面向連接的傳輸層協議,利用IP層傳輸報文時,當目的方網際協議層收到IP報文後,必須識別出該報文所使用的上層協議(即傳輸層協議),因此,在IP報頭上中,設有一個"協議"域(Protocol)。通過該域的值,即可判明其上層協議類型,傳輸層與網路層在功能說的最大區別是前者提供進程通信能力,而後者則不能,在進程通信的意義上,網路通信的最終地址不僅僅是主機地址,還包括可以描述進程的某種標識符,為此,TCP/UDP提出了協議埠(Protocol Port)的概念,用於標識通信的進程,例如,Web伺服器進程通常使用埠80,在/etc/services文件中有這些注冊了的埠地址。
對於TCP傳輸,傳輸節點間先要建立連接,然後通過該連接傳輸已排好序的報文,以保證傳輸的正確性,IP層中的代碼用於實現網際協議,這些代碼將IP頭增加到傳輸數據中,同時也把收到的IP報文正確的傳送到TCP層或UDP層。TCP是一個面向連接協議,而UDP則是一個非面向連接協議,當一個UDP報文發送出去後,Linux並不知道也不去關心他是否成功地到達了目的的主機,IP層之下,是支持所有Linux網路應用的網路設備層,例如點到點協議(Point to Point Protocol,PPP)和乙太網層。網路設備並非總代表物理設備,其中有一些(例如回送設備)則是純粹的軟體設備,網路設備與標準的Linux設備不同,他們不是通過Mknod命令創建的,必須是底層軟體找到並進行了初始化之後,這些設備才被創建並可用。因此只有當啟動了正確設置的乙太網設備驅動程序的內核後,才會有/dev/eth0文件,ARP協議位於IP層和支持地址解析的協議層之間。
網路通信原理所有的網路通信就其實現技術可以分為兩種,線路交換和包交換,計算機網路一般採用包交換,TCP使用了包交換通信技術,計算機網路中所傳輸的數據,全部都以包(Packet)這個單位來發送,包由"報頭"和"報文"組成,結構如圖2所示,在"報頭"中記載有發送主機地址,接收主機地址及與報文內容相關的信息等,在"報文"中記載有需要發送的數據,網路中的每個主機和路由器中都有一個路由定址表,根據這個路由表,包就可以通過網路傳送到相應的目的主機。
網路通信中的一個非常重要的概念就是套接字(Socket)[3,4],簡單地說,套接字就是網路進程的ID,網路通信歸根到底是進程的通信,在網路中,每個節點有一個網路地址(即IP地址),兩個進程通信時,首先要確定各自所在網路節點的網路地址,但是,網路地址只能確定進程所在的計算機,而一台計算機上可能同時有多個網路進程,還不能確定到底是其中的哪個進程,由此套接字中還要有其他的信息,那就是埠號(Port),在一台計算機中,一個埠一次只能分配給一個進程,即埠號與進程是一一對應的關系,所以,埠號和網路地址就能唯一地確定Internet中的一個網路進程。可以認為:套接字=網路地址+埠號系統調用一個Socket()得到一個套接字描述符,然後就可以通過他進行網路通信了。
套接字有很多種類,最常用的就有兩種;流式套接字和數據報套接字。在Linux中分別稱之為"SOCK_STREAM"和"SOCK_DGRAM)"他們分別使用不同的協議,流式套接字使用TCP協議,數據報套接字使用UDP協議,本文所使用的是流式套接字協議。
網路通信原理在文件傳輸程序設計中的應用網路上的絕大多數通信採用的都是客戶機/伺服器機制(Client/Server),即伺服器提供服務,客戶是這些服務的使用者,伺服器首先創建一個Socket,然後將該Socket與本地地址/埠號綁定(Bind()),成功之後就在相應的Socket上監聽(Listen()) 。當Accept()函數捕捉到一個連接服務(Connect())請求時,接受並生成一個新的Socket,並通過這個新的Socket與客戶端通信,客戶端同樣也要創建一個Socket,將該Socket與本地地址/埠號綁定,還需要指定伺服器端的地址與埠號,隨後向伺服器端發出Connect(),請求被伺服器端接受後,可以通過Socket與伺服器端通信。
TCP是一種面向連接的、可靠的、雙向的通信數據流,說他可靠,是因為他使用3段握手協議傳輸數據,並且在傳輸時採用"重傳肯定確認"機制保證數據的正確發送:接收端收到的數據後要發出一個肯定確認,而發送端必須要能接受到這個肯定信號,否則就要將數據重發。在此原理基礎之上,設計了基於Linux操作系統下TCP/IP編程實現文件傳輸的實例。我們採用客戶機/伺服器模式通信時,通信雙方發送/接收數據的工作流程如圖3所示。
文件傳輸就是基於客戶機/伺服器模型而設計的,客戶機和伺服器之間利用TCP建立連續,因文件傳輸是一個互動式會話系統,客戶機每次執行文件傳輸,都需要與伺服器建立控制連接和數據連接,其中控制連接負責傳輸控制信息、利用控制命令、客戶機可以向伺服器提出無限次的請求,客戶機每次提出的請求,伺服器與客戶機建立一個數據連接,進行實際的數據傳輸,數據傳輸完畢後,對應的數據連接被清除,控制連接依然保持,等待客戶機發出新的傳輸請求,直到客戶機撤銷控制連接,結束會話。
當進行文件傳輸時,首先向伺服器發出連接請求,伺服器驗證身份後,與客戶端建立連接,雙方進入會話狀態,這時只要客戶端向伺服器端發出數據連接請求,建立起數據連接後,雙方就進入數據傳輸狀態,數據傳輸完畢後,數據連接被撤銷,如此循環反復,直到會話結束,從而實現將文件從伺服器端傳輸至客戶機端。
文件傳輸程序設計流程[5,客戶端的TCP應用程序流程(1)先用Socket()創建本地套介面,給伺服器端套介面地址結構賦值。
(2)用Connect()函數使本地套介面向伺服器端套介面發出建立連接請求,經3次握手建立TCP連接。
(3)用Read()函數讀取所要接收的文件名以及存放在內存里的文件內容。
(4)用Open()函數打開客戶端新建立的目標文件,如果沒有建立,該函數會自動生成目標文件,等待存放文件內容。
(5)最後用Write()函數將讀取的文件內容存放在新的目標文件中,以實現伺服器端向客戶端的文件傳輸。
(6)通信結束,用Close()關閉套介面,停止接收文件。
伺服器端的TCP應用程序流程(1)先用Open()函數打開等待傳輸的可讀文件;(2)用Socket()創建套介面,並給套介面地址結構賦值;(3)用Bind()函數綁定套介面;(4)用Listen()函數在該套介面上監聽請求;(5)用Accept()函數接受請求,產生新的套介面及描述字,並與客戶端連接;(6)用Lseek()函數是為了在每次接受客戶機連接時,將用於讀的源文件指針移到文件頭;(7)用Read()函數讀取一定長度的源文件數據;(8)最後用Write()函數將讀取的源文件數據存放在內存中,以便客戶端讀取;(9)傳輸完畢時,用Close()關閉所有進程,結束文件傳輸。
結語Linux操作系統在網路應用方面具有很強的開發潛力,同時Linux也是可靠性、安全性非常高的系統,因此在基於TCP/IP網路通信的研究與開發中,通常選用Linux操作系統作為開發平台
❺ Linux編程socket通信疑問
什麼是Socket
Socket介面是TCP/IP網路的API,Socket介面定義了許多函數或常式,程序員可以用它們來開發TCP/IP網路上的應用程序。要學Internet上的TCP/IP網路編程,必須理解Socket介面。
Socket介面設計者......
答案就在這里:linux
socket
通信編程
----------------------Hi,地球人,我是問答機器人小S,上面的內容就是我狂拽酷炫叼炸天的答案,除了贊同,你還有別的選擇嗎?
❻ LINUX網路編程TCP伺服器 客戶端 有亂碼怎麼解決
解決辦法:
1.在客戶端n=read(socketfd,buff,1023);代碼之前加上memset(buff,0,sizeof(buff));,這是保證收到較短數據(使用TCP你不能保證每次接收的數據和發送的數據時等長的),列印也是正確的;
2.將客戶端buff[n+1]+='\0';修改為buff[n]='\0';,這是因為n是下標,已經是最後一個位置了;
3.將伺服器端buff[n+1]+='\0';修改為buff[n]='\0';,這是因為n是下標,已經是最後一個位置了,而且和第2)一樣,那個加號也要去掉,應該是筆誤吧;
4.最大的問題,將伺服器端write(connectfd,buff,1023);,你怎麼能夠保證收到1023個字元呢?也應該將while中條件移出作為WHILE中的一條語句,而且加上前面所述的memset語句,而將這里的write(connectfd,buff,1023);修改為write(connectfd,buff,strlen(buff))。
祝共同進步!
❼ 想問一個 關於linux下 socket編程的問題! 請進
1、 accept函數中,第三個參數原型是 socklen_t的,這是個什麼啊? 編譯的時候總是 說 它和int 的轉換無效! 應該怎麼修改?
a.accept的函數原型為int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);最後一個參數是socklen_t類型,沒記錯的話,他是unsigned int類型。所以譽做拍會有gcc會warning(g++則報錯,g++更嚴格)
2、編譯的時候 命令行輸入的是:
./TCPServer (伺服器IP) (埠號)
我想問的是,這個 伺服器IP和 埠號 在程序裡面是怎麼體現出來的?
是不是 那個 if(argc!=2) 決定的啊? 也就是命令行必須 輸出2個字元串。
如果輸出 三個字元串(包括埠號) 能行么? 哪位高手幫幫我啊!
a.伺服器的IP是寫死在慶羨程序里的,這句,
server_addr.sin_addr.s_addr=htonl(INADDR_ANY);INADDR_ANY表示讓協議棧自己選IP地址(針對多IP的情況);埠體現在這句 server_addr.sin_port=htons(portnumber);程序要求你輸入兩個字元串,其中第一個為程序名,第二個為埠號。比如你編譯出來的程序叫server,則命令為server 8888,就可以執行了。注意這里的argc等於幾表示連程序名稱在內總共有幾個字元串。
4、 最後的 close()函數 作用范圍不明!
因為你調用了socket函數打開了一個描述字sockfd,所以這里要把他關閉。
newfd是你accept返回的描述字,前面已經關了,這兩個是不一樣的。sockfd用來監聽,newfd用來與建立連接的對端通訊。
另外,你露了頭文件,所以warning
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <netdb.h>
#include <sys/types.h>
#include <胡老netinet/in.h>
#include <sys/socket.h>
#define WAITBUF 10
#include <unistd.h>
#include <arpa/inet.h>
int main(int argc, char *argv[])
{
int sockfd,new_fd;
struct sockaddr_in server_addr;
struct sockaddr_in client_addr;
socklen_t sin_size;
int portnumber;
char hello[]="Hello! Socket communication world!\n";
if(argc!=2)
{
fprintf(stderr,"Usage:%s portnumber\a\n",argv[0]);
exit(1);
}
/*埠號不對,退出*/
if((portnumber=atoi(argv[1]))<0)
{
fprintf(stderr,"Usage:%s portnumber\a\n",argv[0]);
exit(1);
}
/*伺服器端開始建立socket描述符*/
if((sockfd=socket(AF_INET,SOCK_STREAM,0))==-1)
{
fprintf(stderr,"Socket error:%s\n\a",strerror(errno));
exit(1);
}
/*伺服器端填充 sockaddr結構*/
bzero(&server_addr,sizeof(struct sockaddr_in));
server_addr.sin_family=AF_INET;
/*自動填充主機IP*/
server_addr.sin_addr.s_addr=htonl(INADDR_ANY);
server_addr.sin_port=htons(portnumber);
/*捆綁sockfd描述符*/
if(bind(sockfd,(struct sockaddr *)(&server_addr),sizeof(struct sockaddr))==-1)
{
fprintf(stderr,"Bind error:%s\n\a",strerror(errno));
exit(1);
}
/*監聽sockfd描述符*/
if(listen(sockfd, WAITBUF)==-1)
{
fprintf(stderr,"Listen error:%s\n\a",strerror(errno));
exit(1);
}
while(1)
{
/*伺服器阻塞,直到客戶程序建立連接*/
sin_size=sizeof(struct sockaddr_in);
if((new_fd=accept(sockfd,(struct sockaddr *)(&client_addr),&sin_size))==-1)
{
fprintf(stderr,"Accept error:%s\n\a",strerror(errno));
exit(1);
}
/*可以在這里加上自己的處理函數*/
fprintf(stderr,"Server get connection from %s\n",
inet_ntoa(client_addr.sin_addr));
if(send(new_fd,hello,strlen(hello),0)==-1)
{
fprintf(stderr,"Write Error:%s\n",strerror(errno));
exit(1);
}
/*這個通信已經結束*/
close(new_fd);
/*循環下一個*/
}
close(sockfd);
exit(0);
}
❽ linux下socket 網路編程(客戶端向伺服器端發送文件) 求源代碼 大哥大姐幫幫忙 ,。。謝謝
源代碼奉上,流程圖。。。這個太簡單了,你自己看看。。。。。。。
//TCP
//伺服器端程序
#include< stdio.h >
#include< stdlib.h >
#include< windows.h >
#include< winsock.h >
#include< string.h >
#pragma comment( lib, "ws2_32.lib" )
#define PORT 2046
#define BACKLOG 10
#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_32.lib" )
#define PORT 2046
#define BACKLOG 10
#define TRUE 1
#define MAXDATASIZE 100
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( "192.168.2.194" );//記得換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_32.lib" )
#define PORT 2046
#define BACKLOG 10
#define TRUE 1
#define MAXDATASIZE 1000
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_32.lib" )
#define PORT 2046
#define MAXDATASIZE 100
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( "192.168.2.194" );//記得換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( );
}