A. DELPHI上簡單高效的SOCKET控制項怎麼選擇
主要用非同步通訊方式
直接api,winsock
參考之:
SOCKET控制項與直接使用API相比
Windows自帶的Tracert是向遠程主機發送ICMP包進行追蹤,但是目前很多主機關閉了ICMP答復,這個工具不太好使了~~~~~原理咱知道,正規的Trace不就是發送TTL依次遞增的UDP包嗎?什麼網關和路由敢隨意丟棄我們的UDP包而不通知我們?ICMP包你可以不理,但是UDP包~~~~~不怕黑你???
unit YRecords;
interface
uses
Windows;
const
PACKET_SIZE = 32;
MAX_PACKET_SIZE = 512;
TRACE_PORT = 34567;
LOCAL_PORT = 5555;
type
s32 = Integer;
u32 = DWORD;
u8 = Byte;
u16 = word; PU16 = ^U16;
//
//IP Packet Header
//
PIPHeader = ^YIPHeader;
YIPHeader = record
u8verlen : u8;//4bits ver, 4bits len, len*4=true length
u8tos : u8;//type of service, 3bits 優先權(現在已經被忽略), 4bits TOS, 最多隻能有1bit為1
u16totallen : u16;//整個IP數據報的長度,以位元組為單位。
u16id : u16;//標識主機發送的每一份數據報。
u16offset : u16;//3bits 標志,13bits片偏移
u8ttl : u8;//生存時間欄位設置了數據報可以經過的最多路由器數。
u8protol : u8;//協議類型,6表示傳輸層是TCP協議。
u16checksum : u16;//首部檢驗和。
u32srcaddr : u32;//源IP地址,不是『xxx.xxx.xxx.xxx』的形勢哦
u32destaddr : u32;//目的IP地址,同上
end;
//
//ICMP Packet Header
//
PICMPHeader = ^YICMPHeader;
YICMPHeader = record
u8type : u8;
u8code : u8;
u16chksum : u16;
u16id : u16;
u16seq : u16;
end;
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, YRecords, winsock2;
type
TForm1 = class(TForm)
ListBox1: TListBox;
Edit1: TEdit;
Button1: TButton;
procere FormCreate(Sender: TObject);
procere FormClose(Sender: TObject; var Action: TCloseAction);
procere Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
function DecodeIcmpReply( pbuf: PChar; var seq: s32 ): string;
var
pIpHdr : PChar;
pIcmphdr : PICMPHeader;
sip : string;
ttl : integer;
begin
pIpHdr := pbuf;
sip := inet_ntoa( TInAddr( PIPHeader(pIpHdr)^.u32srcaddr ) );
ttl := PIPHeader(pIpHdr)^.u8ttl;
Inc( pIpHdr, (PIPHeader(pIpHdr)^.u8verlen and $0F) * 4 );
pIcmpHdr := PICMPHeader(pIpHdr);
result := ;
if pIcmpHdr^.u8type = 3 then //目的不可達信息,Trace完成
seq := 0;
if pIcmpHdr^.u8type = 11 then //超時信息,正在Trace
result := Format( %4d%32s%8d, [seq, sip, ttl] );
end;
procere ErrMsg( msg: string );
begin
MessageBox( 0, PChar(msg), Ping Program Error, MB_ICONERROR );
end;
procere TForm1.FormCreate(Sender: TObject);
var
wsa : TWSAData;
begin
if WSAStartup( $0202, wsa ) <> 0 then
ErrMsg( Windows socket is not responed. );
ListBox1.Font.Name := Courier New;
ListBox1.Font.Size := 9;
end;
procere TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
if WSACleanup <> 0 then
ErrMsg( Windows socket can not be closed. );
end;
procere TForm1.Button1Click(Sender: TObject);
const
SIO_RCVALL = IOC_IN or IOC_VENDOR or 1;
var
rawsock : TSocket;
pRecvBuf : PChar;
FromAdr : TSockAddr;
FromLen : s32;
fd_read : TFDSet;
timev : TTimeVal;
sReply : string;
udpsock : TSocket;
ret : s32;
DestAdr : TSockAddr;
pSendBuf : PChar;
ttl, opt : s32;
pHost : PHostEnt;
begin
//創建一個RAWSOCK接收回應ICMP包
rawsock := socket( AF_INET, SOCK_RAW, IPPROTO_ICMP );
FromAdr.sin_family := AF_INET;
FromAdr.sin_port := htons(0);
FromAdr.sin_addr.S_addr := inet_addr(192.168.1.12); //換成你的IP
//如果不bind就無法接收包了~~~因為下面還要創建一個UDPSOCK
bind( rawsock, @FromAdr, SizeOf(FromAdr) );
Opt := 1;
WSAIoctl( rawsock, SIO_RCVALL, @Opt, SizeOf(Opt), nil, 0, @ret, nil, nil );
//接收ICMP回應包的緩沖區
pRecvBuf := AllocMem( MAX_PACKET_SIZE );
//創建一個UDPSOCK發送探測包
udpsock := socket( AF_INET, SOCK_DGRAM, IPPROTO_UDP );
//要發送的UDP數據
pSendBuf := AllocMem( PACKET_SIZE );
FillChar( pSendBuf^, PACKET_SIZE, C );
FillChar( DestAdr, sizeof(DestAdr), 0 );
DestAdr.sin_family := AF_INET;
DestAdr.sin_port := htons( TRACE_PORT );
DestAdr.sin_addr.S_addr := inet_addr( PChar(Edit1.Text) );
//如果edit1.text不是IP地址,則嘗試解析域名
if DestAdr.sin_addr.S_addr = INADDR_NONE then
begin
pHost := gethostbyname( PChar(Edit1.Text) );
if pHost <> nil then
begin
move( pHost^.h_addr^^, DestAdr.sin_addr, pHost^.h_length );
DestAdr.sin_family := pHost^.h_addrtype;
DestAdr.sin_port := htons( TRACE_PORT );
ListBox1.Items.Add( Edit1.Text +IP地址->+ inet_ntoa(DestAdr.sin_addr) );
end else
begin
ListBox1.Items.Add( 解析域名: + Edit1.Text + 出錯。 );
closesocket( rawsock );
closesocket(udpsock);
FreeMem( pSendBuf );
FreeMem( pRecvBuf );
exit;
end;
end;
ListBox1.Items.Add( Trace route + Edit1.Text + ...... );
Listbox1.Update;
//開始Trace!!!
ttl := 1;
while True do
begin
//設置TTL,使我們發送的UDP包的TTL依次累加
setsockopt( udpsock, IPPROTO_IP, IP_TTL, @ttl, sizeof(ttl) );
//發送UDP包到HOST
sendto( udpsock, pSendBuf^, PACKET_SIZE, 0, DestAdr, sizeof(DestAdr) );
FD_ZERO( fd_read );
FD_SET( rawsock, fd_read );
timev.tv_sec := 5;
timev.tv_usec := 0;
if select( 0, @fd_read, nil, nil, @timev ) < 1 then
break;
if FD_ISSET( rawsock, fd_read ) then
begin
FillChar( pRecvBuf^, MAX_PACKET_SIZE, 0 );
FillChar( FromAdr, sizeof(FromAdr), 0 );
FromAdr.sin_family := AF_INET;
FromLen := sizeof( FromAdr );
recvfrom( rawsock, pRecvBuf^, MAX_PACKET_SIZE, 0, FromAdr, FromLen );
sReply := DecodeIcmpReply( pRecvBuf, ttl );
if sReply <> then
begin
ListBox1.ItemIndex := ListBox1.Items.Add( sReply );
Listbox1.Update;
end;
if ttl = 0 then //如果收到目標主機的相應包,DecodeIcmpReply會把ttl==0
break;
end;
Inc( ttl );
Sleep( 110 );
end; //while not bStop do
ListBox1.Items.Add( 追蹤路由完成。 );
ListBox1.Items.Add( );
closesocket( rawsock );
closesocket(udpsock);
FreeMem( pSendBuf );
FreeMem( pRecvBuf );
end;
end.
------解決方案--------------------
如果壓力較大
感覺標準的不如indy
indy不如api
------解決方案--------------------
upup...
------解決方案--------------------
用INDY好點,API有點復雜
------解決方案--------------------
ICS 用了都說好!
------解決方案--------------------
1000以下的連接用INDY不錯,1000以上考慮自己封裝完成埠。
------解決方案--------------------
所有VCL用FastMM檢測都有哪個內存泄漏的提示,如果只有一個可以忽略,樓主看看源代碼就知道了。
------解決方案--------------------
簡單高效就是serversocket和clientsocket
B. delphi怎樣用socket發送,接受record類型的數據
網路應用分為客戶端和服務端兩部分,而Socket類是負責處理客戶端通信的java類。通過這個類可以連接到指定IP或域名的伺服器上,並且可以和伺服器互相發送和接受數據。在本文及後面的數篇文章中將詳細討論Socket類的使用,內容包括Socket類基礎、各式各樣的連接方式、get和set方法、連接過程中的超時以及關閉網路連接等。
在本文中,我們將討論使用Socket類的基本步驟和方法。一般網路客戶端程序在連接服務程序時要進行以下三步操作。
1.連接伺服器
2.發送和接收數據
3.關閉網路連接
一、連接伺服器
在客戶端可以通過兩種方式來連接伺服器,一種是通過IP的方式來連接伺服器,而另外一種是通過域名方式來連接伺服器。
其實這兩種方式從本質上來看是一種方式。在底層客戶端都是通過IP來連接伺服器的,但這兩種方式有一定的差異,如果通過IP方式來連接服務端程序,客戶端只簡單地根據IP進行連接,如果通過域名來連接伺服器,客戶端必須通過DNS將域名解析成IP,然後再根據這個IP來進行連接。
在很多程序設計語言或開發工具中(如C/C++、Delphi)使用域名方式連接伺服器時必須自己先將域名解析成IP,然後再通過IP進行連接,而在Java中已經將域名解析功能包含在了Socket類中,因此,我們只需象使用IP一樣使用域名即可。
通過Socket類連接伺服器程序最常用的方法就是通過Socket類的構造函數將IP或域名以及埠號作為參數傳入Socket類中。Socket類的構造函數有很多重載形式,在這一節只討論其中最常用的一種形式:public Socket(String host, int port)。從這個構造函數的定義來看,只需要將IP或域名以及埠號直接傳入構造函數即可。下面的代碼是一個連接服務端程序的例子程序:
package mysocket;
import java.net.*;
public class MyConnection
{
public static void main(String[] args)
{
try
{
if (args.length > 0)
{
Socket socket = new Socket(args[0], 80);
System.out.println(args[0] + "已連接成功!");
}
else
System.out.println("請指定IP或域名!");
}
catch (Exception e)
{
System.err.println("錯誤信息:" + e.getMessage());
}
}
}
在上面的中,通過命令行參數將IP或域名傳入程序,然後通過Socket socket = new Socket(args[0], 80)連接通過命令行參數所指定的IP或域名的80埠。由於Socket類的構造函數在定義時使用了throws,因此,在調用Socket類的構造函數時,必須使用try…catch語句來捕捉錯誤,或者對main函數使用throws語句來拋出錯誤。
測試正確的IP
java mysocket.MyConnection 127.0.0.1
輸出結果:127.0.0.1已經連接成功!
測試錯誤的IP
java mysocket.MyConnection 10.10.10.10
輸出結果:錯誤信息:Connection timed out: connect
註:10.10.10.10是一個並不存在的IP,如果這個IP在你的網路中存在,請使用其它的不存在的IP。
測試正確的域名
java mysocket.MyConnection www.ptpress.com.cn
輸出結果:www.ptpress.com.cn已經連接成功!
測試錯誤的域名
java mysocket.MyConnection www.ptpress1.com.cn
輸出結果:錯誤信息:www.ptpress1.com.cn
使用Socket類連接伺服器可以判斷一台主機有哪些埠被打開。下面的代碼是一個掃描本機有哪些埠被打開的程序。
C. 在delphi中如何用clientsocket進行實時發送。。即在資料庫讀取到數據就立即發送出去。。
如果是資料庫中直接可以發送出去的話, 就用觸發器。
如果是自己開發程序, 需要程序來發送出去的話, 就在程序中用Timer控制項,
在OnTimer事件中讀取資料庫中A表數據, A表需要用觸發器來寫入數據, 可以把需要發送出去的數據在觸發器中寫入到A表, 那麼在程序每次讀取到A表數據後就通過程序來發送, 這個不難吧?
我不知道你要發送的是具體數據呢, 還是數據集, 數據集就相對比較麻煩點了, 我也沒研究過這個, 不知道是否可以用Stream來操作。
D. 誰能給我一個用Delphi寫SOCKS5代理伺服器的常式
所謂代理伺服器 就是代理網路用戶去取得網路信息。形象的說,它是網路信息的中轉站.
E. Delphi下的socket(如TServerSocket)為什麼沒有超時屬性,
waitfor函數來確定一個socket的超時設置,有msgwaitformultipleobjects,
msgwaitforsingleobject,
或用winsock.select函數也可。如果是block方式一般用線程方式來操作,使用waitfor來確定是否超時,或有數據來。。。通過setsockopt可以設置socket
recv
buffer
sizesetsockopt(clientsocket1.socket.sockethandle,
SOL_SOCKET,SO_recv{這參數叫接收buffer,查一下help},
pchar(&BufSize),
SizeOf(BufSize));
具體看一下scktcomp.pas源碼
查看原帖>>
F. delphi socket編程 幫忙看下
這樣寫其實是有點問題的,立即連接馬上就發送,個人認為在將來網路上應用的話肯定會丟失發送內容,不知具體如何,到時你試過如果真的完全沒有問題麻煩告訴我一聲。
至於你說發送出去別人收到的都不對,估計是因為bs:array of byte;的問題!!
如果你是這樣定義的話bs:array[0..3] of byte; 且不要下面的setlength那句,應該別人收到的是對的
G. 如何用delphi socket 傳遞自定義對象
參考代碼:
(1) delphi客戶端發送:
csConnect()中
tmpstr := ipcode + '|setclient|' + ip + '|' + mac + '|' + #13#10;
Socket.SendText(tmpstr);
(2)Java服務接受:
public ServerThread2(Socket s) { // serverThread的構造器
this.request = s;
// 接收receiveServer傳來的套接字
try { // 初始化輸入、輸出流
response = new DataOutputStream(request.getOutputStream());
input = new DataInputStream(request.getInputStream());
} catch (IOException e) {
GlobaTx.LogLn(e.getMessage());
}
}
@Override
public void run() { // 線程的執行方法
String str = "";
//StringBuilder sb=new StringBuilder();
str = input.readLine();
//下邊詳細處理
}
(3)java服務端返回:
/**
* 發送報文到客戶端
* @param response
* @param pg
* @return
*/
public static boolean writePg(DataOutputStream response, DataPg pg) {
try {
String tmp=pg.getReturnStr()+"*";
System.out.println("sender:"+tmp);
response.writeBytes(tmp);//(s)writeUTF
response.flush();
return true;
} catch (IOException e) {
e.printStackTrace();
return false;
} finally {
}
}
(4)delphi客戶端接收:
csRead()中
res := Socket.ReceiveText;
tmpstr := res[length(res)];
if tmpstr <> '*' then //約定的結束字元*,防止傳送不完整串
begin
pgcs := pgcs + res;
Exit;
end;
res := pgcs + res;
pgcs := '';
--------------------------------------------------------------------------------------------------------------------
大文件傳送:
(1)delphi發送
procere TForm1.csfileConnect(Sender: TObject; Socket: TCustomWinSocket);
var
Buf: array[1..MAX_BUF + 1] of char;
bytes, iLength, MySendLength: Integer;
res, tmpstr, Msg: string;
bufSend: pointer;
picname: string; //保存的照片名稱
ipcode: string; //機器編號
timestr: string; //時間
lt: TSYSTEMTIME;
begin
res := pg;
ipcode := tools.findsegment(res, 1, '|');
GetLocalTime(lt);
picname := ipcode + '-' + inttostr(lt.wYear) +
inttostr(lt.wMonth) + inttostr(lt.wDay) + inttostr(lt.wHour)
+ inttostr(lt.wMinute) + inttostr(lt.wSecond) + '.bmp';
tools.CaptureScreen(picname);
while tools.IsFileInUse(picname) do
begin
end;
fsSend := TFileStream.Create(picname, fmOpenRead);
Socket.SendText(ipcode + '|uppic|' + picname + '|' + inttostr(fsSend.Size) + '|' + #13#10);
if fsSend.Size > 0 then
begin
while fsSend.Position < fsSend.Size do
begin
iLength := fsSend.Size;
// - fsSend.Position;
//將數據分段發送
// if iLength > MAX_BUF then
// iLength := MAX_BUF;
GetMem(bufSend, iLength);
try
//讀取文件流數據
fsSend.Read(bufSend^, iLength);
//發送長度為iLength的數據
Socket.SendBuf(bufSend^, iLength);
//進度條顯示
// Probar.Position := fsSend.Position;
finally
//釋放內存
FreeMem(bufSend, iLength);
end;
end;
//Socket.Close();
Timer1.Enabled := True;
end;
end;
(2)java接收
public static boolean fileWriteIn(File file, DataInputStream downStream,long length) {
FileOutputStream fileWrite = null;
try {
fileWrite = new FileOutputStream(file);
byte[] buffer = new byte[size];
int len = 0;
long n = 0;
System.out.print(" >開始接受數據,寫入文件 ");
while ((len = downStream.read(buffer, 0, size)) != -1) {
fileWrite.write(buffer, 0, len);
n += len;
System.out.print(".");
if ((n + size) > length) {
int lastLen = (int) (length - n);
n += lastLen;
len = downStream.read(buffer, 0, lastLen);
fileWrite.write(buffer, 0, len);
System.out.print("-");
break;
}
}
System.out.println(" >完成接受,長度為:" + n);
//接收完成==========================
return true;
} catch (Exception e) {
e.printStackTrace();
System.out.println("Error: " + e.getMessage());
return false;
} finally {
try {
fileWrite.close();
} catch (IOException e) {
}
}
}
----------------------------------------------------------------------------
中文傳送:
msg:=UTF8Decode(HttpDecode(msg)) ;
// URLdecode(msg);
showmessage(Msg);
destr = URLEncoder.encode(body, "utf-8");
System.out.println("-URL-----------"+destr+"------------");
H. delphi中使用sock或tcp/udp
可以使用Delphi自帶的控制項TTcpClient。
使用步驟:設置好主機地址和埠;響應連接事件,在連接事件中記錄連接狀態;響應讀數據事件,顯示收到的數據;調用連接方法;連接後按伺服器要求的格式發送數據;完畢。
I. socket 編程問題~~~~~~~急~~~~~~~~~~Access violation at address
可能是系統連接數受限吧,你可以在程序中斷開某一個連接,給它騰位置
J. delphi中如何實現多線程socket通信時
我再說具體些,在delphi中實現收集socket通信時,應用TserverSocket類做辦事器端,個中該類的ServerType屬性有兩個選擇,分別決定辦事器端是為每個客戶request生成一個線程(選stThreadBlocking)照樣所有的客戶request都在一個線程中處理(選stNonBlocking),當我選擇stThreadBlocking用線程方法時,客戶端發送信息時,辦事器端不克不及激活OnClientRead事宜,而被選擇非線程方法時則可以實現。