Ⅰ Windows Socket和linux Socket編程的區別 ZZ
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
一、linux下的socket編程:
1、客戶端執行步驟依次如下:
socket()
connect()
send()或者recv()
close()
注意的是,connect之前要填充地址結構體,IP地址轉換為網路位元組序,一般用inet_aton().
2、伺服器端:
socket()
bind()
listen()
accpet()
recv()或者send()
close()
(ps:一般通過將send()和recv()的最後一個參數賦為0或者1來區分阻塞與非阻塞,其中0對應阻塞,1對應非阻塞)
二、windows下的網路編程:
做過windows網路編程的人都知道,微軟的MFC把復雜的WinSock API函數封裝到類里,這使得編寫網路應用程序更容易。即windows既提供上層的網路API函數也提供底層的API函數。
1、對於採用上層的API函數而言:若採用csocket類定義一個對象obj的話,那麼進行網路編程的步驟如下:
客戶端:
obj.Create()
obj.Connect()
obj.Receive()或者obj.Send()
obj.Close()
伺服器端:
先調用AfxSocketInit()檢測協議棧安裝情況
obj.Create()
obj.Listen()
obj.Accpet()
obj.Receive()或者obj.Send()
obj.Close()
2、對於採用底層的API函數而言,步驟如下:
客戶端:
WSAStartup()
socket()
connect()
send()或者recv()
closesocket()
伺服器端:
WSAStartup()
socket()
bind()
listen()
accpet()
send()
recv()
closesocket()
(ps:windows下CSocket類為同步方式,有阻塞現象;CASyncSocket為非同步方式,無阻塞現象。)
通過以上比較可以發現:linux下的網路編程與windows下採用底層的API類似,但是也有區別:
區別一:windows下需加上WSAStartup()函數
區別二:關閉socket:linux為close(),windows為closesocket()
windows下採用上層的API,一般有CSocket和CAsynSocket這兩種類型的類
這種情況以下socket函數一般的首字母大寫。而底層的API不管是windows下的還是linux下的socket函數首字母都是小寫的。
Ⅱ Linux下Socket編程 怎樣實現客戶端之間互相通信
網路的Socket數據傳輸是一種特殊的I/O,Socket也是一種文件描述符。Socket也具有一個類似於打開文件的函數調用Socket(),該函數返回一個整型的Socket描述符,隨後的連接建立、數據傳輸等操作都是通過該Socket實現的。
下面用Socket實現一個windows下的c語言socket通信例子,這里我們客戶端傳遞一個字元串,伺服器端進行接收。
【伺服器端】
#include"stdafx.h"
#include<stdio.h>
#include<winsock2.h>
#include<winsock2.h>
#defineSERVER_PORT5208//偵聽埠
voidmain()
{
WORDwVersionRequested;
WSADATAwsaData;
intret,nLeft,length;
SOCKETsListen,sServer;//偵聽套接字,連接套接字
structsockaddr_insaServer,saClient;//地址信息
char*ptr;//用於遍歷信息的指針
//WinSock初始化
wVersionRequested=MAKEWORD(2,2);//希望使用的WinSockDLL的版本
ret=WSAStartup(wVersionRequested,&wsaData);
if(ret!=0)
{
printf("WSAStartup()failed! ");
return;
}
//創建Socket,使用TCP協議
sListen=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
if(sListen==INVALID_SOCKET)
{
WSACleanup();
printf("socket()faild! ");
return;
}
//構建本地地址信息
saServer.sin_family=AF_INET;//地址家族
saServer.sin_port=htons(SERVER_PORT);//注意轉化為網路位元組序
saServer.sin_addr.S_un.S_addr=htonl(INADDR_ANY);//使用INADDR_ANY指示任意地址
//綁定
ret=bind(sListen,(structsockaddr*)&saServer,sizeof(saServer));
if(ret==SOCKET_ERROR)
{
printf("bind()faild!code:%d ",WSAGetLastError());
closesocket(sListen);//關閉套接字
WSACleanup();
return;
}
//偵聽連接請求
ret=listen(sListen,5);
if(ret==SOCKET_ERROR)
{
printf("listen()faild!code:%d ",WSAGetLastError());
closesocket(sListen);//關閉套接字
return;
}
printf("Waitingforclientconnecting! ");
printf("Tips:Ctrl+ctoquit! ");
//阻塞等待接受客戶端連接
while(1)//循環監聽客戶端,永遠不停止,所以,在本項目中,我們沒有心跳包。
{
length=sizeof(saClient);
sServer=accept(sListen,(structsockaddr*)&saClient,&length);
if(sServer==INVALID_SOCKET)
{
printf("accept()faild!code:%d ",WSAGetLastError());
closesocket(sListen);//關閉套接字
WSACleanup();
return;
}
charreceiveMessage[5000];
nLeft=sizeof(receiveMessage);
ptr=(char*)&receiveMessage;
while(nLeft>0)
{
//接收數據
ret=recv(sServer,ptr,5000,0);
if(ret==SOCKET_ERROR)
{
printf("recv()failed! ");
return;
}
if(ret==0)//客戶端已經關閉連接
{
printf("Clienthasclosedtheconnection ");
break;
}
nLeft-=ret;
ptr+=ret;
}
printf("receivemessage:%s ",receiveMessage);//列印我們接收到的消息。
}
//closesocket(sListen);
//closesocket(sServer);
//WSACleanup();
}
【客戶端】
#include"stdafx.h"
#include<stdio.h>
#include<stdlib.h>
#include<winsock2.h>
#defineSERVER_PORT5208//偵聽埠
voidmain()
{
WORDwVersionRequested;
WSADATAwsaData;
intret;
SOCKETsClient;//連接套接字
structsockaddr_insaServer;//地址信息
char*ptr;
BOOLfSuccess=TRUE;
//WinSock初始化
wVersionRequested=MAKEWORD(2,2);//希望使用的WinSockDLL的版本
ret=WSAStartup(wVersionRequested,&wsaData);
if(ret!=0)
{
printf("WSAStartup()failed! ");
return;
}
//確認WinSockDLL支持版本2.2
if(LOBYTE(wsaData.wVersion)!=2||HIBYTE(wsaData.wVersion)!=2)
{
WSACleanup();
printf("InvalidWinSockversion! ");
return;
}
//創建Socket,使用TCP協議
sClient=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
if(sClient==INVALID_SOCKET)
{
WSACleanup();
printf("socket()failed! ");
return;
}
//構建伺服器地址信息
saServer.sin_family=AF_INET;//地址家族
saServer.sin_port=htons(SERVER_PORT);//注意轉化為網路節序
saServer.sin_addr.S_un.S_addr=inet_addr("192.168.1.127");
//連接伺服器
ret=connect(sClient,(structsockaddr*)&saServer,sizeof(saServer));
if(ret==SOCKET_ERROR)
{
printf("connect()failed! ");
closesocket(sClient);//關閉套接字
WSACleanup();
return;
}
charsendMessage[]="hellothisisclientmessage!";
ret=send(sClient,(char*)&sendMessage,sizeof(sendMessage),0);
if(ret==SOCKET_ERROR)
{
printf("send()failed! ");
}
else
printf("clientinfohasbeensent!");
closesocket(sClient);//關閉套接字
WSACleanup();
}
Ⅲ Linux操作系統下Socket編程地址結構介紹
linux下的網路通信程序,一定要和一個結構打交道,這個結構就是socket
address。比如bind、connect等等函數都要使用socket
address結構。理解socket
address時我們要明白,其實在linux下針對於不同的socket
domain定義了一個通用的地址結構struct
sockaddr,它的具體定義為:
{unsigned
short
int
sa_family;char
sa_data[14];}
struct
sockaddr
其中,sa_family為調用socket()函數時的參數domain參數,sa_data為14個字元長度存儲。針對於不同domain下的socket,通用地址結構又對應了不同的定義,例如一般的AF_INET
domain下,socket
address的定義如下:
struct
sockaddr_in{unsigned
short
int
sin_family;uint16_t
sin_port;struct
in_addr
sin_addr;unsigned
char
sin_zero[8];//未使用}struct
in_addr{uint32_t
s_addr;}
當socket的domain不同於AF_INET時,具體的地址定義又是不同的,但是整個地址結構的大小、容量都是和通用地址結構一致的。
Ⅳ 在Linux系統下編寫一個socket程序
我給你一個更高端的
#include <stdlib.h>
#include <sys/types.h>
#include <stdio.h>
#include <sys/socket.h>
#include <linux/in.h>
#include <string.h>
#define M 8888
struct qun
{
int cy[5];
};
struct haoyou
{
int py[5];
};
struct ri
{
int geren[5];
};
int main()
{
struct qun group[5]={0};
struct haoyou pyd[5]={0};
struct ri ziji[5]={0};
printf("server onil\n");
printf("this port is %d\n",M);
fd_set rest;
int servsock=socket(AF_INET,SOCK_STREAM,0);
if(-1==servsock)
{
perror("socket perror");
return 1;
}
struct sockaddr_in servaddr;
struct sockaddr_in clienaddr;
servaddr.sin_family=AF_INET;
servaddr.sin_addr.s_addr=htonl(INADDR_ANY);
servaddr.sin_port=htons(M);
int a=bind(servsock,(struct sockaddr *)&servaddr,sizeof(servaddr));
if(-1==a)
{
perror("bind perror\n");
return 1;
}
int b=listen(servsock,5);
if(-1==b)
{
perror("listen perror");
return 1;
}
FD_ZERO(&rest);
char sendbuff[1024];
char recvbuff[1024];
int n;
int qw;
int r[10];
int min[1024]={0};
int i=0;
int iWho[10]={0};
int mabi[1024]={0};
char mingzi[10][50]={0};
char caonima[1024]={0};
int wocao[10]={0};
n=sizeof(clienaddr);
struct timeval time;
while(1)
{
time.tv_sec = 0;
time.tv_usec = 470;
FD_SET(servsock,&rest);
FD_SET(fileno(stdin),&rest);
select(servsock+1,&rest,NULL,NULL,&time);
if(FD_ISSET(servsock,&rest))
{
r[i]=accept(servsock,(struct sockaddr *)&clienaddr,&n);
if(r[i]==-1)
{
i--;
}
i++;
}
int p;
for(p=0;p<i;p++)
{
FD_SET(r[p],&rest);
}
int ret=select(r[i-1]+1,&rest,NULL,NULL,&time);
if(ret<0)
{
printf("socket error\n");
continue;
}
else
{
int u;
for(u=0;u<i;u++
Ⅳ LINUX網路編程中socket函數詳細解釋下吧
函數原型:int socket(int family,int type,int protocol); 參數解釋:family指定協議簇,UNIX下(包括linux)有:AF_INET,AF_INET6,AF_LOCAL,AF_ROUTE,AF_KEY,分別是IPv4,IPv6協議,UNIX域協議,路由套介面,密鑰套介面; type指定套介面類型:unix下有四種,分別是:SOCK_STREAM,SOCK_DGRAM,SOCK_SEQPACKET,SOCK_RAW。(流套接字,數據報套接字,有序分組套接字,原始套接字),SOCK_SEQPACKET已很少使用; protocol:IPPROTO_TCP,IPPROTO_UDP,IPPROTO_SCTP,分別是TCP傳輸協議,UDP傳輸協議,SCTP傳輸協議; 函數返回一個非負整數值,類似於文件描述符(linux內核知識),稱之為套介面描述字,簡稱套接字。《Linux就該這么學》這本書,希望你能感受到linux系統和這本書帶給你的好處及幫助。
Ⅵ linux socket 編程
這類問題,你不用考慮太復雜的,可以直接使用socket提供的tcp服務介面,通過send和recv等函數處理就行了。數據建議自行寫封裝和解封函數,
介面類似這樣:int pack(char *, struct data *); int unpack(char *, struct data *);
可以按照你自己的喜好,將你的struct按照你的方式填入一個char*裡面(你直接將struct data*類型轉換後賦值給char*類型都行),然後就可以使用介面了;
你完全不用管tcp的實現機制的,tcp有擁塞控制,超時重傳,自動分包等機制,可以保證你的數據按准確的方式送達;
像什麼包的數據頭什麼的,如果你需要定義的是應用層的協議,或者你希望自定義網路層和傳輸層(使用raw方式的socket),你才需要考慮;
Ⅶ Linux socket編程
#include<stdio.h>
#include<stdlib.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<netdb.h>
char *host_name="127.0.0.1";
int port=7778;
struct student
{
char name[20];
char num[20];
float score;
}t={"xiejian","200701415",89.9};
int main ( )
{
char buf[502];
int socket_descriptor;
struct sockaddr_in pin;
bzero(&pin,sizeof(pin));
pin.sin_family=AF_INET;
inet_pton(AF_INET,host_name,&pin.sin_addr);
pin.sin_port=htons(port);
if((socket_descriptor=socket(AF_INET,SOCK_STREAM,0))==-1)
{
perror("Error openung socket!\n");
exit(1);
}
if(connect(socket_descriptor,(void *)&pin,sizeof (pin))==-1)
{
perror("can not connecting to server!\n");
exit (1);
}
printf("Send message to server ...\n");
//memset(buf,0,502);
//memcpy(buf,(void *)&t,sizeof(t));
//sprintf(buf,"%s %d",t.name,t.num);
//printf("the first string : %s\n",buf);
if(send(socket_descriptor,(void *) &t,sizeof(t),0)==-1)
{
perror("can not send message!\n");
exit (1);
}
printf("waiting for response from server!\n");
memset(buf,0,502);
if(recv(socket_descriptor,buf,sizeof(buf),0)==-1)
{
perror("can not receive response !\n");
exit (1);
}
printf("\n Response from server : \n");
memcpy((struct student *)&t,buf,sizeof(buf));
//printf("the string : %s \n",rebuf);
printf("--%s--%s--%5.1f--\n",t.name,t.num,t.score);
close (socket_descriptor);
}
/* 注意在send 結構體時應該把結構體強制類型轉換為void * 型
** 接受之後又要強制轉換回結構體型!否則則穿過來的是結構體的
** 一部分!
*/
下面是服務端
#include<stdio.h>
#include<stdlib.h>
#include<netinet/in.h>
#include<sys/socket.h>
#include<arpa/inet.h>
#include<netdb.h>
int port=7778;
struct student
{
char name[20];
char num[20];
float score;
}t;
main()
{
struct sockaddr_in sin;
struct sockaddr_in pin;
int sock_descriptor;
int temp_sock_descriptor;
int size_of_addr;
//struct cfg a;
char buf[502];
int i,lenth;
sock_descriptor=socket(AF_INET,SOCK_STREAM,0);
if(sock_descriptor==-1)
{
perror("socket!\n");
exit(1);
}
bzero(&sin,sizeof(sin));
sin.sin_addr.s_addr=INADDR_ANY;
sin.sin_port=htons(port);
if(bind(sock_descriptor,(struct sockaddr *)&sin,sizeof (sin))==-1)
{
perror("bind!\n");
exit(1);
}
if(listen (sock_descriptor,20)==-1)
{
perror("listen!\n");
exit(1);
}
printf("Waiting for accepting connection from client!\n");
while(1)
{
printf("the process is waiting here!\n");
temp_sock_descriptor=accept(sock_descriptor, (struct sockaddr *)&pin,&size_of_addr);
if(temp_sock_descriptor==-1)
{
perror("call to accept!\n");
exit (1);
}
memset(buf,0,502);
if(recv(temp_sock_descriptor,buf,sizeof(buf),0)==-1)
{
perror("recv!\n");
exit (1);
}
printf("received : \n");
//printf("the recv buf is :%s\n",buf);
memcpy((struct student *) &t,buf,sizeof(buf));
printf("--%s--%s--%5.1f--\n",t.name,t.num,t.score);
if(send (temp_sock_descriptor,(void *) &t,sizeof(t),0)==-1)
{
perror("send!\n");
exit(1);
}
close (temp_sock_descriptor);
}
}
Ⅷ linux下的socket編程
同學,你希望從哪個方面入手進行完善呢?或者說你遇到什麼問題?!!
你的程序健壯性是很不錯的,就是太復雜,我給個最簡單的。接收和顯示放一塊:
void read_and_echo(in fd)
{
char buf[512]={0};
int rc;
while (1)
{
rc=read(fd,buf,511);// 讀入511個字元
buf[rc]=0;// 截斷
printf("Reveive Message: %s",buf);
}
}
Ⅸ 求linux下的socket 編程
看這個代碼你最好了解一下tcp協議,了解一下三次握手機制,要不然你可能看不懂,當初我們學到這的時候學了一天的tcp....還有,就是把下面代碼分開放到2個.c文件中,必須先運行伺服器端,再運行客戶端
//伺服器端的代碼
1 #include <stdio.h>
2 #include <string.h>
3 #include <sys/socket.h>
4 #include <unistd.h>
5 #include <netinet/in.h>
6 #include <sys/stat.h>
7 #include <stdlib.h>
8 #include <arpa/inet.h>
9
10 #define LOCAL_PORT 1234
11 #define MAX_LEN 512
12 #define MAX_NUM 5
13
14 int main(int argc, char *argv[])
15 {
16 int sock_fd, sock_data;
17 int ret, len_addr;
18 char buf[MAX_LEN];
19 ssize_t len;
20 struct sockaddr_in local_addr, remote_addr;
21
22 sock_fd = socket(AF_INET, SOCK_STREAM, 0); //創建套接字,sock_fd是套接字描述符,類似我們的身份證號碼
23 if (sock_fd < 0)
24 {
25 perror("socket()");
26 return sock_fd;
27 }
28
29 local_addr.sin_family = AF_INET;// 協議族,ipv4
30 local_addr.sin_port = htons(LOCAL_PORT);// 把伺服器埠轉換成網路位元組序
31 local_addr.sin_addr.s_addr = inet_addr("127.0.0.1");//把字元串形式的ip轉換成網路位元組序
32
33 ret = bind(sock_fd, (struct sockaddr *)&local_addr, (size_t)sizeof(local_addr));// 把sock_fd和本機ip,埠邦定
34 if (ret < 0)
35 {
36 perror("bind()");
37 close(sock_fd);
38 return ret;
39 }
40
41 ret = listen(sock_fd, MAX_NUM);//監聽socket
42 if (ret)
43 {
44 perror("listen()");
45 close(sock_fd);
46 return ret;
47 }
48
49 memset(buf, 0, MAX_LEN);
50
51 len_addr = sizeof(remote_addr);
52
53 sock_data = accept(sock_fd, (struct sockaddr *)&remote_addr, (socklen_t *)&len_addr);//接受客戶端的連接
54 if (ret < 0)
55 {
56 perror("accept()");
57 close(sock_fd);
58 return ret;
59 }
60
61 while (1)
62 {
63 int slen;
64 len = recv(sock_data, buf, MAX_LEN, 0);//接受客戶端的數據
65 if (len < 0)
66 {
67 perror("recv()");
68 close(sock_data);
69 close(sock_fd);
70 return len;
71 }
72 printf("%s\n", buf);
73
74 slen = send(sock_data, "congratulation!", 15, 0);//向客戶端發送數據
75 if (slen <= 0)
76 {
77 printf("slen = %d\n", slen);
78 perror("send()");
79 close(sock_data);
80 close(sock_fd);
81 return slen;
82 }
83 sleep(1);
84 }
85
86 close(sock_data);
87 close(sock_fd);
88
89 return 0; }
//客戶端代碼
1 #include <stdio.h>
2 #include <string.h>
3 #include <sys/socket.h>
4 #include <unistd.h>
5 #include <netinet/in.h>
6 #include <sys/stat.h>
7 #include <stdlib.h>
8 #include <arpa/inet.h>
9
10 #define REMOTE_PORT 1234
11 #define MAX_LEN 512
12
13 int main(int argc, char *argv[])
14 {
15 int sock_fd, ret;
16 int len;
17 char buf[MAX_LEN];
18 struct sockaddr_in local_addr, remote_addr;
19
20 sock_fd = socket(AF_INET, SOCK_STREAM, 0);
21 if (sock_fd < 0)
22 {
23 perror("socket()");
24 return sock_fd;
25 }
26
28 local_addr.sin_family = AF_INET;
29 local_addr.sin_addr.s_addr = htonl(INADDR_ANY); //自動獲取本機的ip地址
30 local_addr.sin_port = htons(0); //隨機選取可用的埠,並不是指定埠為0
31
33 remote_addr.sin_family= AF_INET;
34 remote_addr.sin_port = htons(REMOTE_PORT);
35 ret = inet_aton("127.0.0.1", &remote_addr.sin_addr);
36
38 ret = bind(sock_fd, (struct sockaddr *)&local_addr, sizeof(local_addr)); //把本機的ip,port和socket綁定
39 if (ret < 0)
40 {
41 perror("bind() !");
42 close(sock_fd);
43 return ret;
44 }
45
47 ret = connect(sock_fd, (struct sockaddr *)&remote_addr, (socklen_t)sizeof(remote_addr)); //把本機的socket和對方的port,ip建立連接
48 if (ret < 0)
49 {
50 perror("connect()");
51 close(sock_fd);
52 return ret;
53 }
54
55 memset(buf, 0, MAX_LEN);
56
57 while (1)
58 {
59 int i;
60 // len = send(sock_fd, buf, (size_t)MAX_LEN, 0);
61 len = send(sock_fd, "hello", 6, 0);
62 if (len <= 0)
63 {
64 perror("send()");
65 close(sock_fd);
66 return ret;
67 }
68
69 // printf("%d-->bytes send!\n", len);
70 sleep(1);
71
72 len = recv(sock_fd, buf, MAX_LEN, 0);
73 if (len <= 0)
74 {
75 perror("recv()");
76 close(sock_fd);
77 return ret;
78 }
79
80 for (i = 0; i < len; i++)
81 {
82 printf("%c", buf[i]);
83 }
84 printf("\n");
85 }
86
87 close(sock_fd);
88
89 return 0;
90 }
Ⅹ linux下socket編程,怎樣把文件和文件屬性一起發送到伺服器端
socket可以發送任意類型的數據。socket本身不限制你要發送什麼,而是由你自己來定要發什麼的。只要你接收端能識別發來的是什麼即可。
協議的三個基本要素,語法、語義、同步。比如你用於表示文件屬性的結構體或者其他什麼數據長度固定是20位元組,那麼你就在發送文件內容之前把這20位元組發送過去,接收端在接收內容之前,固定會先接收20位元組並作為文件屬性,隨後接收到的內容才作為數據存入文件,這樣就可以做到了。
關鍵點就在於自己要定好語法、語義、同步這些,發送端和接收端配合好動作。