客户机通过IP加端口号来访问连接服务器上提供的网络服务
端口号可以唯一标识一个服务,不同类型的服务可以共用同一个端口号
Socket套接字,服务器可以用ServerSocket监听客户机的连接,需要用IP和PORT来构建一个ServerSocket
当调用ServerSocket.accept()方法时,服务器一直阻塞在此,等待客户机的连接,返回的Socket包含了客户机的一些信息
可以通过返回的Socket来和客户机交流,Socket.getOutputStream()来往客户机写数据,Socket.getInputStream()来读取客户机的写给服务机的数据
客户机(使用Socket)要想跟服务机取得连接,必须要指定服务机的IP和提供该服务的场所(端口号),使用Socket.getOutputStream()和Socket.getInputStream()来读写数据
客户机和服务机写数据时,必须刷新缓冲区(数据是被写到缓冲区内的),否则只有当默认的缓冲区满时,数据才会进行传输
由于Socket使用了非常重要的非内存资源,所以必须谨慎正确的清除它
下面是一个简单的客户机和服务器连接通信的例子
public class TCPServer {
public static final int PORT = 8090;
/**
* @param args
* @throws IOException
*/
public static void main(String[] args) throws IOException {
ServerSocket s = new ServerSocket(PORT);
System.out.println("s:"+s);
try{
Socket scoket = s.accept();
System.out.println("scoket:"+scoket);
try{
BufferedReader in = new BufferedReader(
new InputStreamReader(
scoket.getInputStream()));
//自动刷新缓冲区,否则要当缓冲区慢才会进行传输
PrintWriter out = new PrintWriter(
new BufferedWriter(
new OutputStreamWriter(
scoket.getOutputStream())),true);
while(true){
//和client实现一次“握手”
String str = in.readLine();
//连接结束的条件
if(str.equals("END")) break;
System.out.println("Echoing:"+str);
//send package to client
out.println(str);
}
}finally{
scoket.close();
}
}finally{
s.close();
}
}
}
public class TCPClient {
/**
* @param args
* @throws IOException
*/
public static void main(String[] args) throws IOException {
InetAddress inetAddress = InetAddress.getByName(null);
System.out.println("inetAddress:"+inetAddress);
Socket socket = new Socket(inetAddress,TCPServer.PORT);
System.out.println("socket:"+socket);
try{
BufferedReader in = new BufferedReader(
new InputStreamReader(
socket.getInputStream()));
//自动刷新缓冲区,否则要当缓冲区慢才会进行传输
PrintWriter out = new PrintWriter(
new BufferedWriter(
new OutputStreamWriter(
socket.getOutputStream())),true);
for(int i=0;i<10;i++){
//send package to server ,wait server echo
out.println("Hello "+i);
String str = in.readLine();
System.out.println("Enchoing:"+str);
}
out.println("END");
}finally{
socket.close();
}
}
}
TCP是一种可靠的传输协议,它可以确保传输的数据准确的到达目的地而不会有数据的丢失,而UDP是一种不可靠的传输协议,有可能传输的数据中会给你丢失一部分,TCP需要占用非常大的资源且数据传输的比较慢,而UDP占用资源小且数据传输快
UDP是以一种数据包的形式陈列的,数据包在传输的过程中有可能丢失,也有可能传输的顺序会发生改变,但如果对传输速度要求比较快的话,UDP还是有用武之地的,向QQ、网络游戏啥的
下面是一个简单的UDP例子
public class UDPServer {
public static int serverPort = 8097;
DatagramSocket socket;
//提供一个缓冲区,用于存放接收的数据
byte[] buf = new byte[1000];
//保存数据信息的场所
DatagramPacket dp = new DatagramPacket(buf,buf.length);
public UDPServer(){
try {
//要指定监听那个端口
socket = new DatagramSocket(serverPort);
System.out.println("socket:"+socket);
while(true){
//阻塞
socket.receive(dp);
//通过接收的数据包可以取得发包方的信息
String receiveData = "receive data:"+Dgram.toString(dp)+" from inetAddress:"+dp.getAddress()+" the port:"+dp.getPort();
System.out.println("receiveData:"+receiveData);
String echoing = "echo "+receiveData;
//发送到那个地址和端口
socket.send(Dgram.toDatagram(echoing, dp.getAddress(), dp.getPort()));
}
} catch (SocketException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
new UDPServer();
}
}
public class UDPClient extends Thread{
DatagramSocket socket;
byte[] buf = new byte[1000];
DatagramPacket dp = new DatagramPacket(buf,buf.length);
int clientId;
InetAddress serverAddress;
public UDPClient(int id) {
clientId = id;
try {
socket = new DatagramSocket();
serverAddress = InetAddress.getByName("localhost");
System.out.println("serverAddress:"+serverAddress);
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (SocketException e) {
e.printStackTrace();
}
}
@Override
public void run() {
for (int i = 0; i < 10; i++) {
String sendMsg = "Client "+clientId+" Message "+i;
try {
//指定发送到地址和端口
socket.send(Dgram.toDatagram(sendMsg, serverAddress, UDPServer.serverPort));
socket.receive(dp);
//数据包可以取得发包方的信息
String receiveData = "Client "+clientId+" from address "+dp.getAddress()+" and port "+dp.getPort()
+" receive data "+Dgram.toString(dp);
System.out.println("receive data "+receiveData);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
/**
* @param args
*/
public static void main(String[] args) {
for (int i = 0; i < 15; i++){
new UDPClient(i).start();
}
}
}
用到的工具类
public class Dgram {
public static DatagramPacket toDatagram(String str,
InetAddress ia,int inetPort){
byte[] buf = new byte[str.length()];
buf = str.getBytes();
return new DatagramPacket(buf, buf.length,ia, inetPort);
}
public static String toString(DatagramPacket dp){
return new String(dp.getData(),0,dp.getLength());
}
}

最后附上一个示例程序,其中包含了TCP服务多个客户机程序