㈠ 在windows下,如何用純C語言實現socket網路編程
mfc只是對socket進行了一些封裝,大部分人做網路編程都是用的原始的socket,比如如下介面都可以在c下進行調用
1.socket()
2.bind()
3.connect()
4.listen()
5.accept()
6.send() 和recv()
7.sendto() 和recvfrom()
8.close() 和shutdown()
9.getpeername()
10.gethostname()
這些介面是在Winsock2.h中定義的不是在mfc中定義的,你只需要包含Winsock2.h頭文件和Ws2_32.lib庫就可以了。
㈡ 用java的socket編程實現c/s結構程序
今天太晚了,改天給你做一個,記得提醒我,這個如果只是要個簡單的,我半個小時就搞定了
給我個郵箱
現在給貼出我的代碼: 整個結構分兩個工程
1。服務端工程NioServer.java: 採用nio 方式的非同步socket通信,不僅可以實現你的伺服器還可以讓你多學習一下什麼是nio
2。客戶端工程UserClient.java: 採用Swing技術畫了一個簡單的UI界面,比較土,原因是我沒那麼多時間去設計界面,你需要的話可以自己去修改得漂亮點,相信不難
現在貼工程1:
package com.net;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util.Set;
public class NioServer {
public static final int SERVERPORT=5555;
public static final String USERNAME="wangrong";
public static final String PASSWORD="123456";
public static final String ISACK="ACK";
public static final String ISNAK="NAK!";
// Selector selector;//選擇器
// SelectionKey key;//key。 一個key代表一個Selector 在NIO通道上的注冊,類似主鍵;
// //取得這個Key後就可以對Selector在通道上進行操作
private ByteBuffer echoBuffer = ByteBuffer.allocate( 1024 );// 通道數據緩沖區
public NioServer(){
}
public static void main(String[] args) throws IOException {
NioServer ns=new NioServer();
ns.BuildNioServer();
}
public void BuildNioServer() throws IOException{
/////////////////////////////////////////////////////////
///////先對服務端的ServerSocket進行注冊,注冊到Selector ////
/////////////////////////////////////////////////////////
ServerSocketChannel ssc = ServerSocketChannel.open();//新建NIO通道
ssc.configureBlocking( false );//使通道為非阻塞
ServerSocket ss = ssc.socket();//創建基於NIO通道的socket連接
//新建socket通道的埠
ss.bind(new InetSocketAddress("127.0.0.1",SERVERPORT));
Selector selector=Selector.open();//獲取一個選擇器
//將NIO通道選綁定到擇器,當然綁定後分配的主鍵為skey
SelectionKey skey = ssc.register( selector, SelectionKey.OP_ACCEPT );
////////////////////////////////////////////////////////////////////
//// 接收客戶端的連接Socket,並將此Socket也接連注冊到Selector ////
///////////////////////////////////////////////////////////////////
while(true){
int num = selector.select();//獲取通道內是否有選擇器的關心事件
if(num<1){continue; }
Set selectedKeys = selector.selectedKeys();//獲取通道內關心事件的集合
Iterator it = selectedKeys.iterator();
while (it.hasNext()) {//遍歷每個事件
try{
SelectionKey key = (SelectionKey)it.next();
//有一個新聯接接入事件,服務端事件
if ((key.readyOps() & SelectionKey.OP_ACCEPT)
== SelectionKey.OP_ACCEPT) {
// 接收這個新連接
ServerSocketChannel serverChanel = (ServerSocketChannel)key.channel();
//從serverSocketChannel中創建出與客戶端的連接socketChannel
SocketChannel sc = serverChanel.accept();
sc.configureBlocking( false );
// Add the new connection to the selector
// 把新連接注冊到選擇器
SelectionKey newKey = sc.register( selector,
SelectionKey.OP_READ );
it.remove();
System.out.println( "Got connection from "+sc );
}else
//讀客戶端數據的事件,此時有客戶端發數據過來,客戶端事件
if((key.readyOps() & SelectionKey.OP_READ)
== SelectionKey.OP_READ){
// 讀取數據
SocketChannel sc = (SocketChannel)key.channel();
int bytesEchoed = 0;
while((bytesEchoed = sc.read(echoBuffer))> 0){
System.out.println("bytesEchoed:"+bytesEchoed);
}
echoBuffer.flip();
System.out.println("limet:"+echoBuffer.limit());
byte [] content = new byte[echoBuffer.limit()];
echoBuffer.get(content);
String result=new String(content);
doPost(result,sc);
echoBuffer.clear();
it.remove();
}
}catch(Exception e){}
}
}
}
public void doPost(String str,SocketChannel sc){
boolean isok=false;
int index=str.indexOf('|');
if(index>0){
String name=str.substring(0,index);
String pswd=str.substring(index+1);
if(pswd==null){pswd="";}
if(name!=null){
if(name.equals(USERNAME)
&& pswd.equals(PASSWORD)
){
isok=true;
}else{
isok=false;
}
}else{
isok=false;
}
}else{
isok=false;
}
String result="";
if(isok){
result="ACK";
}else{
result="NAK!";
}
ByteBuffer bb = ByteBuffer.allocate( result.length() );
bb.put(result.getBytes());
bb.flip();
try {
sc.write(bb);
} catch (IOException e) {
e.printStackTrace();
}
bb.clear();
}
}
下面貼工程2
import java.awt.Color;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.net.UnknownHostException;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JPasswordField;
import javax.swing.JTextField;
public class UserClient implements ActionListener{
JFrame jf;
JPanel jp;
JLabel label_name;
JLabel label_pswd;
JTextField userName;
JButton jb;
JPasswordField paswrd;
JLabel hintStr;
public UserClient (){
jf=new JFrame("XXX 登陸系統");
jp=new JPanel();
jf.setContentPane(jp);
jf.setPreferredSize(new Dimension(350,220));
jp.setPreferredSize(new Dimension(350,220));
jp.setBackground(Color.gray);
label_name=new JLabel();
label_name.setPreferredSize(new Dimension(150,30));
label_name.setText("請輸入帳戶(數字或英文):");
userName=new JTextField();
userName.setPreferredSize(new Dimension(150,30));
jp.add(label_name);
jp.add(userName);
label_pswd=new JLabel();
label_pswd.setPreferredSize(new Dimension(150,30));
label_pswd.setText("請輸入密碼:");
jp.add(label_pswd);
paswrd=new JPasswordField();
paswrd.setPreferredSize(new Dimension(150,30));
jp.add(paswrd);
jb=new JButton("OK");
jb.setPreferredSize(new Dimension(150,30));
jb.setText("確 定");
jb.addActionListener( this);
jp.add(jb);
hintStr=new JLabel();
hintStr.setPreferredSize(new Dimension(210,40));
hintStr.setText("");
hintStr.setForeground(Color.RED);
jp.add(hintStr);
jf.pack();
jf.setVisible(true);
jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
private String name;
private String pswd;
public void actionPerformed(ActionEvent e) {
name=userName.getText().trim();
pswd=new String(paswrd.getPassword());
if(pswd==null){
pswd="";
}else{
pswd=pswd.trim();
}
if(name!=null && name.length()>0){
hintStr.setText("正在驗證客戶端,請稍候...");
start();
}
}
OutputStream os;
Socket s;
InputStream is;
public void start(){
//建立聯網線程
new Thread(new Runnable(){
public void run() {
try {
s=new Socket("127.0.0.1",5555);
//寫
os=s.getOutputStream();
os.write(name.getBytes());
os.write('|');//用戶名與密碼用"|"分隔
os.write(pswd.getBytes());
os.flush();
//讀內容
Thread.sleep(1000);
is=s.getInputStream();
int len=is.available();
System.out.println("len:"+len);
byte[] bytes=new byte[len];
is.read(bytes);
String resut=new String(bytes);
System.out.println("resut:"+resut);
//TODO 這里通過返回結果處理
if(resut.equals("ACK")){
hintStr.setText("驗證成功,歡迎光臨!");
}else{
paswrd.setText(null);
hintStr.setText("用戶名或密碼錯誤,請重新輸入");
}
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}finally{
// try {
// os.close();
// is.close();
// s.close();
// } catch (IOException e) {
// e.printStackTrace();
// }
}
}
}).start();
}
public static void main(String[] args) {
new UserClient();
}
}
㈢ C語言socket編程問題 急急急。。。。
首先要寫個什麼都不幹的c/s程序
s端:
int main(void)
{
int sockfd, confd;
struct sockaddr_in ser, cli;
int len;
sockfd = socket(PF_INET, SOCK_STREAM, 0);
bzero(ser, sizeof(ser));
ser.sin_family = PF_INET;
ser.sin_port = htons(8080);
ser.sin_addr.s_addr = htonl(INADDR_ANY);//任何ip主機都接收
bind(sockfd, (struct sockaddr *)&ser, sizeof(ser));//綁定套接字
listen(scokfd, 20);
printf("receive message..........\n");
while(1)
{
len = sizeof(cil);
confd = accept(sockfd, (struct sockaddr *)&cli, &len);//confd用於處理網路連接
read();
write();
close(confd);
}
return 0;
}
------------------------------------------------------------------
c端
main()
{
int sockfd;
struct sockaddr_indest_addr;
sockfd = socket(PF_INET,SOCK_STREAM,0);
dest_addr.sin_family=PF_INET;
dest_addr.sin_port=htons(8080);//必須一樣,要問為什麼自己看埠號是干什麼用的
dest_addr.sin_addr.s_addr=htonl(主機ip);
connect(sockfd,(structsockaddr*)&dest_addr,sizeof(struct sockaddr));
while(1)
{
write();
read();
if()
break;
}
close();
}
-------------------------------------------------------------
框架我給你搭好了。
中間部分由你自己回答。
記住傳送文件的時候,同步很重要。
㈣ 怎樣用C語言做socket網路編程
mfc只是對socket進行了一些封裝,大部分人做網路編程都是用的原始的socket,比如如下介面都可以在c下進行調用
1.socket()
2.bind()
3.connect()
4.listen()
5.accept()
6.send() 和recv()
7.sendto() 和recvfrom()
8.close() 和shutdown()
9.getpeername()
10.gethostname()
這些介面是在Winsock2.h中定義的不是在mfc中定義的,你只需要包含Winsock2.h頭文件和Ws2_32.lib庫就可以了。
㈤ C#socket非同步怎麼實現 線程間通信如何實現
基於C#的socket編程的TCP非同步實現
一、摘要
本篇博文闡述基於TCP通信協議的非同步實現。
二、實驗平台
Visual Studio 2010
三、非同步通信實現原理及常用方法
3.1 建立連接
在同步模式中,在伺服器上使用Accept方法接入連接請求,而在客戶端則使用Connect方法來連接伺服器。相對地,在非同步模式下,伺服器可以使用BeginAccept方法和EndAccept方法來完成連接到客戶端的任務,在客戶端則通過BeginConnect方法和EndConnect方法來實現與伺服器的連接。
BeginAccept在非同步方式下傳入的連接嘗試,它允許其他動作而不必等待連接建立才繼續執行後面程序。在調用BeginAccept之前,必須使用Listen方法來偵聽是否有連接請求,BeginAccept的函數原型為:
BeginAccept(AsyncCallback AsyncCallback, Ojbect state)
參數:
AsyncCallBack:代表回調函數
state:表示狀態信息,必須保證state中包含socket的句柄
使用BeginAccept的基本流程是:
(1)創建本地終節點,並新建套接字與本地終節點進行綁定;
(2)在埠上偵聽是否有新的連接請求;
(3)請求開始接入新的連接,傳入Socket的實例或者StateOjbect的實例。
參考代碼:
復制代碼
//定義IP地址
IPAddress local = IPAddress.Parse("127.0,0,1");
IPEndPoint iep = new IPEndPoint(local,13000);
//創建伺服器的socket對象
Socket server = new Socket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp);
server.Bind(iep);
server.Listen(20);
server.BeginAccecpt(new AsyncCallback(Accept),server);
復制代碼
當BeginAccept()方法調用結束後,一旦新的連接發生,將調用回調函數,而該回調函數必須包括用來結束接入連接操作的EndAccept()方法。
該方法參數列表為 Socket EndAccept(IAsyncResult iar)
下面為回調函數的實例:
復制代碼
void Accept(IAsyncResult iar)
{
//還原傳入的原始套接字
Socket MyServer = (Socket)iar.AsyncState;
//在原始套接字上調用EndAccept方法,返回新的套接字
Socket service = MyServer.EndAccept(iar);
}
復制代碼
至此,伺服器端已經准備好了。客戶端應通過BeginConnect方法和EndConnect來遠程連接主機。在調用BeginConnect方法時必須注冊相應的回調函數並且至少傳遞一個Socket的實例給state參數,以保證EndConnect方法中能使用原始的套接字。下面是一段是BeginConnect的調用:
Socket socket=new Socket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp)
IPAddress ip=IPAddress.Parse("127.0.0.1");
IPEndPoint iep=new IPEndPoint(ip,13000);
socket.BeginConnect(iep, new AsyncCallback(Connect),socket);
EndConnect是一種阻塞方法,用於完成BeginConnect方法的非同步連接誒遠程主機的請求。在注冊了回調函數後必須接收BeginConnect方法返回的IASynccReuslt作為參數。下面為代碼演示:
復制代碼
void Connect(IAsyncResult iar)
{
Socket client=(Socket)iar.AsyncState;
try
{
client.EndConnect(iar);
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
finally
{
}
}
復制代碼
除了採用上述方法建立連接之後,也可以採用TcpListener類裡面的方法進行連接建立。下面是伺服器端對關於TcpListener類使用BeginAccetpTcpClient方法處理一個傳入的連接嘗試。以下是使用BeginAccetpTcpClient方法和EndAccetpTcpClient方法的代碼:
復制代碼
public static void DoBeginAccept(TcpListener listner)
{
//開始從客戶端監聽連接
Console.WriteLine("Waitting for a connection");
//接收連接
//開始准備接入新的連接,一旦有新連接嘗試則調用回調函數DoAcceptTcpCliet
listner.BeginAcceptTcpClient(new AsyncCallback(DoAcceptTcpCliet), listner);
}
//處理客戶端的連接
public static void DoAcceptTcpCliet(IAsyncResult iar)
{
//還原原始的TcpListner對象
TcpListener listener = (TcpListener)iar.AsyncState;
//完成連接的動作,並返回新的TcpClient
TcpClient client = listener.EndAcceptTcpClient(iar);
Console.WriteLine("連接成功");
}
復制代碼
代碼的處理邏輯為:
(1)調用BeginAccetpTcpClient方法開開始連接新的連接,當連接視圖發生時,回調函數被調用以完成連接操作;
(2)上面DoAcceptTcpCliet方法通過AsyncState屬性獲得由BeginAcceptTcpClient傳入的listner實例;
(3)在得到listener對象後,用它調用EndAcceptTcpClient方法,該方法返回新的包含客戶端信息的TcpClient。
BeginConnect方法和EndConnect方法可用於客戶端嘗試建立與服務端的連接,這里和第一種方法並無區別。下面看實例:
復制代碼
public void doBeginConnect(IAsyncResult iar)
{
Socket client=(Socket)iar.AsyncState;
//開始與遠程主機進行連接
client.BeginConnect(serverIP[0],13000,requestCallBack,client);
Console.WriteLine("開始與伺服器進行連接");
}
private void requestCallBack(IAsyncResult iar)
{
try
{
//還原原始的TcpClient對象
TcpClient client=(TcpClient)iar.AsyncState;
//
client.EndConnect(iar);
Console.WriteLine("與伺服器{0}連接成功",client.Client.RemoteEndPoint);
}
catch(Exception e)
{
Console.WriteLine(e.ToString());
}
finally
{
}
}
復制代碼
以上是建立連接的兩種方法。可根據需要選擇使用。
3.2 發送與接受數據
在建立了套接字的連接後,就可以伺服器端和客戶端之間進行數據通信了。非同步套接字用BeginSend和EndSend方法來負責數據的發送。注意在調用BeginSend方法前要確保雙方都已經建立連接,否則會出異常。下面演示代碼:
復制代碼
private static void Send(Socket handler, String data)
{
// Convert the string data to byte data using ASCII encoding.
byte[] byteData = Encoding.ASCII.GetBytes(data);
// Begin sending the data to the remote device.
handler.BeginSend(byteData, 0, byteData.Length, 0, new AsyncCallback(SendCallback), handler);
}
private static void SendCallback(IAsyncResult ar)
{
try
{
// Retrieve the socket from the state object.
Socket handler = (Socket)ar.AsyncState;
// Complete sending the data to the remote device.
int bytesSent = handler.EndSend(ar);
Console.WriteLine("Sent {0} bytes to client.", bytesSent);
handler.Shutdown(SocketShutdown.Both);
handler.Close();
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}
復制代碼
接收數據是通過BeginReceive和EndReceive方法:
復制代碼
private static void Receive(Socket client)
{
try
{
// Create the state object.
StateObject state = new StateObject();
state.workSocket = client;
// Begin receiving the data from the remote device.
client.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ReceiveCallback), state);
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}
private static void ReceiveCallback(IAsyncResult ar)
{
try
{
// Retrieve the state object and the client socket
// from the asynchronous state object.
StateObject state = (StateObject)ar.AsyncState;
Socket client = state.workSocket;
// Read data from the remote device.
int bytesRead = client.EndReceive(ar);
if (bytesRead > 0)
{
// There might be more data, so store the data received so far.
state.sb.Append(Encoding.ASCII.GetString(state.buffer, 0, bytesRead));
// Get the rest of the data.
client.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ReceiveCallback), state);
}
else
{
// All the data has arrived; put it in response.
if (state.sb.Length > 1)
{
response = state.sb.ToString();
}
// Signal that all bytes have been received.
receiveDone.Set();
}
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}
復制代碼
上述代碼的處理邏輯為:
(1)首先處理連接的回調函數里得到的通訊套接字client,接著開始接收數據;
(2)當數據發送到緩沖區中,BeginReceive方法試圖從buffer數組中讀取長度為buffer.length的數據塊,並返回接收到的數據量bytesRead。最後接收並列印數據。除了上述方法外,還可以使用基於NetworkStream相關的非同步發送和接收方法,下面是基於NetworkStream相關的非同步發送和接收方法的使用介紹。
NetworkStream使用BeginRead和EndRead方法進行讀操作,使用BeginWreite和EndWrete方法進行寫操作,下面看實例:
復制代碼
static void DataHandle(TcpClient client)
{
TcpClient tcpClient = client;
//使用TcpClient的GetStream方法獲取網路流
NetworkStream ns = tcpClient.GetStream();
//檢查網路流是否可讀
if(ns.CanRead)
{
//定義緩沖區
byte[] read = new byte[1024];
ns.BeginRead(read,0,read.Length,new AsyncCallback(myReadCallBack),ns);
}
else
{
Console.WriteLine("無法從網路中讀取流數據");
}
}
public static void myReadCallBack(IAsyncResult iar)
{
NetworkStream ns = (NetworkStream)iar.AsyncState;
byte[] read = new byte[1024];
String data = "";
int recv;
recv = ns.EndRead(iar);
data = String.Concat(data, Encoding.ASCII.GetString(read, 0, recv));
//接收到的消息長度可能大於緩沖區總大小,反復循環直到讀完為止
while (ns.DataAvailable)
{
ns.BeginRead(read, 0, read.Length, new AsyncCallback(myReadCallBack), ns);
}
//列印
Console.WriteLine("您收到的信息是" + data);
}
復制代碼
3.3 程序阻塞與非同步中的同步問題
.Net里提供了EventWaitHandle類來表示一個線程的同步事件。EventWaitHandle即事件等待句柄,他允許線程通過操作系統互發信號和等待彼此的信號來達到線程同步的目的。這個類有2個子類,分別為AutoRestEevnt(自動重置)和ManualRestEvent(手動重置)。下面是線程同步的幾個方法:
(1)Rset方法:將事件狀態設為非終止狀態,導致線程阻塞。這里的線程阻塞是指允許其他需要等待的線程進行阻塞即讓含WaitOne()方法的線程阻塞;
(2)Set方法:將事件狀態設為終止狀態,允許一個或多個等待線程繼續。該方法發送一個信號給操作系統,讓處於等待的某個線程從阻塞狀態轉換為繼續運行,即WaitOne方法的線程不在阻塞;
(3)WaitOne方法:阻塞當前線程,直到當前的等待句柄收到信號。此方法將一直使本線程處於阻塞狀態直到收到信號為止,即當其他非阻塞進程調用set方法時可以繼續執行。
復制代碼
public static void StartListening()
{
// Data buffer for incoming data.
byte[] bytes = new Byte[1024];
// Establish the local endpoint for the socket.
// The DNS name of the computer
// running the listener is "host.contoso.com".
//IPHostEntry ipHostInfo = Dns.Resolve(Dns.GetHostName());
//IPAddress ipAddress = ipHostInfo.AddressList[0];
IPAddress ipAddress = IPAddress.Parse("127.0.0.1");
IPEndPoint localEndPoint = new IPEndPoint(ipAddress, 11000);
// Create a TCP/IP socket.
Socket listener = new Socket(AddressFamily.InterNetwork,SocketType.Stream, ProtocolType.Tcp);
// Bind the socket to the local
//endpoint and listen for incoming connections.
try
{
listener.Bind(localEndPoint);
listener.Listen(100);
while (true)
{
// Set the event to nonsignaled state.
allDone.Reset();
// Start an asynchronous socket to listen for connections.
Console.WriteLine("Waiting for a connection...");
listener.BeginAccept(new AsyncCallback(AcceptCallback),listener);
// Wait until a connection is made before continuing.
allDone.WaitOne();
}
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
Console.WriteLine("\nPress ENTER to continue...");
Console.Read();
}
復制代碼
上述代碼的邏輯為:
(1)試用了ManualRestEvent對象創建一個等待句柄,在調用BeginAccept方法前使用Rest方法允許其他線程阻塞;
(2)為了防止在連接完成之前對套接字進行讀寫操作,務必要在BeginAccept方法後調用WaitOne來讓線程進入阻塞狀態。
當有連接接入後系統會自動調用會調用回調函數,所以當代碼執行到回調函數時說明連接已經成功,並在函數的第一句就調用Set方法讓處於等待的線程可以繼續執行。
㈥ 關於c#的Socket非同步網路編程問題
這樣的寫法有點問題:
1)伺服器端既然採用了非同步方式Accept,就沒有必要再啟線程
2)估計allDone是一個ManualResetEvent。用ManualResetEvent的目的什麼呢?
伺服器端採用非同步Accept的代碼其實很簡單,也不需要ManualResetEvent同步
publicclassAppTCPServer
{
publicAppTCPServer(stringlocalIP,intport)
{
Socketsocket=newSocket(AddressFamily.InterNetwork,
SocketType.Stream,
ProtocolType.Tcp);
EndPointlocalEP=newIPEndPoint(IPAddress.Parse(localIP),port);
socket.Bind(localEP);
socket.Listen(100);
socket.BeginAccept(AcceptAsync,socket);
}
privatevoidAcceptAsync(IAsyncResultar)
{
Socketsocket=ar.AsyncStateasSocket;
try
{
Socketclient=socket.EndAccept(ar);
Console.WriteLine("客戶端連接成功!客戶端:{0}",client.RemoteEndPoint.ToString());
if(OnConnected!=null)
{
OnConnected(this,newClientConnectedEventArgs(client));
}
}
catch(Exceptione)
{
Console.WriteLine("AcceptAsync發生異常,異常信息: {0}",e.Message);
}
finally
{
//繼續非同步Accept
socket.BeginAccept(AcceptAsync,socket);
}
}
//客戶端連接後的事件OnConnect
publiceventEventHandler<ClientConnectedEventArgs>OnConnected;
}
///<summary>
///事件參數:接收客戶端連接後的事件參數
///</summary>
:EventArgs
{
(SocketclientSocket)
{
ClientSocket=clientSocket;
}
publicSocketClientSocket{get;privateset;}
}
classProgram
{
staticvoidMain(string[]args)
{
AppTCPServerserver=newAppTCPServer("127.0.0.01",8000);
server.OnConnected+=server_OnConnected;
Console.WriteLine("按任意鍵結束程序……");
Console.ReadKey();
}
staticvoidserver_OnConnected(objectsender,ClientConnectedEventArgse)
{
Socketclient=e.ClientSocket;
stringhello="HellofromAppTCPServer";
client.Send(Encoding.Default.GetBytes(hello));
}
}
客戶端測試程序
classProgram
{
staticvoidMain(string[]args)
{
//模擬100個客戶連接伺服器
for(inti=0;i<100;i++)
{
Socketsocket=ConnectToServer("127.0.0.1",8000);
byte[]buffer=newbyte[1024];
intbytesRecevied=socket.Receive(buffer,buffer.Length,SocketFlags.None);
byte[]messageBytes=newbyte[bytesRecevied];
Array.Copy(buffer,messageBytes,bytesRecevied);
Console.WriteLine(Encoding.Default.GetString(messageBytes));
socket.Disconnect(false);
socket.Close();
}
Console.ReadKey();staticSocketConnectToServer(stringserverIP,intserverPort)
{
Socketsocket=newSocket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp);
EndPointlocalEP=newIPEndPoint(IPAddress.Any,0);
socket.Bind(localEP);
socket.Connect(newIPEndPoint(IPAddress.Parse(serverIP),serverPort));
returnsocket;
}
}
㈦ c socket 非同步接收 回調函數啥時候調用
回調函數是由操作系統內核調用的。
准確地說,是在檢測到對應的事件之後被調用。
比如你注冊了一個連接回調,連接到來後,操作系統調用回調。
㈧ C語言socket編程實現網路數據傳輸
僅供參考
// serverTCP.cpp : 定義控制台應用程序的入口點。
//
#include "stdafx.h"
using namespace std;
long long cnt = 0;
void transFile(SOCKET s)
{
printf("新子服務%d......",cnt);
send(s,"welcome to TCP FILE SERVER !",strlen("welcome to TCP FILE SERVER !")+1,0);
char Buf[BUFSIZE];
FILE *fp;
//printf("客戶端已打開\n請輸入存放文件地址:\n");
char FilePath[128]={"0"};
ltoa(cnt,FilePath,10);
if((fp=fopen(FilePath,"wb"))==NULL)
{
printf("文件未打開\n");
return;
}
else
{
send(s,"開始傳送",strlen("開始傳送")+1,0);
//得到文件大小
char Size[20];
long int FileSize=0;
recv(s,Size,21,0);
FileSize=atol(Size);
printf("得到文件大小: %d\n",FileSize);
//開始傳送
char Block[BUFSIZE];
long int x=0;
while (1)
{
x += BUFSIZE;
if(x < FileSize)
{
recv(s,Block,BUFSIZE+1,0);
fwrite(Block,1,BUFSIZE,fp);
}
else
{
recv(s,Block,FileSize+BUFSIZE-x+1,0);
printf("文件接收完畢\n");
fwrite(Block,1,FileSize+BUFSIZE-x,fp);
fclose(fp);
break;
}
}
}
fclose(fp);
closesocket(s);
}
int _tmain(int argc, _TCHAR* argv[])
{
WORD myVersionRequest;
WSADATA wsaData;
myVersionRequest=MAKEWORD(1,1);
int err;
err = WSAStartup(myVersionRequest,&wsaData);
if (!err)
{
printf("伺服器啟動......\n");
}
else
{
printf("伺服器啟動失敗!");
exit(0);
}
SOCKET serSocket = socket(AF_INET,SOCK_STREAM,0);//創建了可識別套接字
SOCKADDR_IN addr;
addr.sin_family=AF_INET;
addr.sin_addr.S_un.S_addr=htonl(INADDR_ANY);//ip地址
addr.sin_port=htons(PORTBASE);//綁定埠
bind(serSocket,(SOCKADDR*)&addr,sizeof(SOCKADDR));//綁定完成
listen(serSocket,ACESIZE);//其中第二個參數代表能夠接收的最多的連接數
SOCKADDR_IN clientAddr;
int len = sizeof(SOCKADDR);
while(1)
{
cnt++;
SOCKET serConn;
serConn = accept(serSocket,(SOCKADDR*)&clientAddr,&len);//如果這里不是accept而是conection的話。。就會不斷的監聽
if(_beginthread((void (*)(void *))transFile, ACESIZE,(void *)serConn) < 0) return 0;
}
return 0;
}
// clientTCP.cpp : 定義控制台應用程序的入口點。
//
#include "stdafx.h"
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
WORD myVersionRequest;
WSADATA wsaData;
myVersionRequest=MAKEWORD(1,1);
int err;
err=WSAStartup(myVersionRequest,&wsaData);
if (!err)
{
printf("已打開套接字\n");
}
else
{
//進一步綁定套接字
printf("套接字未打開!");
return 0;
}
SOCKET cliSocket =socket(AF_INET,SOCK_STREAM,0);
SOCKADDR_IN addr;
char ip_addr[16]={"127.0.0.1"};
addr.sin_addr.S_un.S_addr=inet_addr(ip_addr);
addr.sin_family=AF_INET;
addr.sin_port=htons(PORT);
char ACK[64];
connect(cliSocket,(SOCKADDR*)&addr,sizeof(SOCKADDR));//開始連接
recv(cliSocket,ACK,sizeof(ACK),0);
printf("%s\n",ACK);
FILE *fp;
int FileSize=0;
char Block[BUFSIZE]={"0"};
char FilePath[128]={"0"};
int i=0;
do
{
printf("請輸入文件地址:\n");
gets(FilePath);
i = 0;
if((fp=fopen(FilePath,"rb"))==NULL)
{
i = 1;
printf("文件打開失敗\n");
}
}while(i);
fseek(fp,0L,SEEK_END);
FileSize=ftell(fp);
printf("待傳送文件大小: %d\n",FileSize);
printf("等待伺服器接受......\n");
recv(cliSocket,Block,sizeof(Block),0);
printf("%s\n",Block);
if(strcmp(Block,"開始傳送")==0)
{
char Size[20];
ltoa(FileSize,Size,10);
send(cliSocket,Size,sizeof(Size),0);
fseek(fp,0L,SEEK_SET);
long int y=0;
char trans[BUFSIZE];
while(!feof(fp))
{
fread(trans,1,BUFSIZE,fp);
y=y+BUFSIZE;
if(y<FileSize)
{
send(cliSocket,trans,BUFSIZE+1,0);
}
else
{
send(cliSocket,trans,FileSize+BUFSIZE-y+1,0);
closesocket(cliSocket);
WSACleanup();
}
}
}
printf("文件發送完畢\n");
fclose(fp);
closesocket(cliSocket);
WSACleanup();
system("pause");
return 0;
}
㈨ 在windows下用C語言如何實現socket網路編程,需要用到哪些頭文件或者庫
需要用到的頭文件包含:
#include <winsock2.h>
#include <windows.h>
與Linux環境下socket編程相比,windows環境多了一個步驟:啟動或者初始化winsock庫
Winsock,一種標准API,一種網路編程介面,用於兩個或多個應用程序(或進程)之間通過網路進行數據通信。具有兩個版本:
Winsock 1:
Windows CE平台支持。
頭文件:WinSock.h
庫:wsock32.lib
Winsock 2:
部分平台如Windows CE貌似不支持。通過前綴WSA可以區別於Winsock 1版本。個別函數如WSAStartup、WSACleanup、WSARecvEx、WSAGetLastError都屬於Winsock 1.1規范的函數;
頭文件:WinSock2.h
庫:ws2_32.lib
mswsock.h用於編程擴展,使用時必須鏈接mswsock.dll
(9)csocket非同步編程擴展閱讀
winsock庫的載入與卸載:
載入:int WSAStartup(WORD wVersionRequested, LPWSADATA lpWSAData);
載入成功,返回值為0。
WORD wVersionRequested:載入的winsock版本,使用宏MAKEWORD(x, y),x表示高位元組,y表示低位元組。然而使用時MAKEWORD(2, 2)。高位元組與低位元組相同~~
LPWSADATA lpWSAData:WSADATA結構的指針,傳入參數後,系統幫助我們填充版本信息。有興趣的可以看看結構體內容,不過基本用不著。
卸載:int WSACleanup(void);比起載入,卸載的函數真是輕松愉快。
㈩ C語言socket編程
send用戶名和密碼,然後再伺服器判斷這段字元串的賬號密碼是否符合,然後客戶端recv,如果recv的字元串是登錄成功,才進行下面操作.否則就提示用戶名和密碼有誤.